couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject [02/50] couch commit: updated refs/remotes/origin/import to 09c6556
Date Mon, 10 Feb 2014 20:05:02 GMT
Assume success when we replicate an existing leaf

The logic in couch_db:prep_and_validate_replicated_updates/5 was broken
if we attempt to replicate a leaf that exists. The function has
explicitly commented logic that if we attempt to replicate an internal
node of the revision tree that we just ignore it and assume success.
While the logic matched the comment, what the comment should say is that
if we replicate an existing revision then we should treat is as a
successful no-op.

The way that the error manifests with the old logic is that we would try
and run make_first_doc_on_disk which reads through all previous
revisions on the edit path to find the first available revision.
Although if we had compacted then none would exist so that the
make_first_doc_on_disk function would return nil and attempt to use that
where we wanted a #doc{} in couch_doc:merge_stubs/2.

BugzId: 15562


Branch: refs/remotes/origin/import
Commit: 4cc61f1ba02d87b7190f5c014b93dd21cf5a5503
Parents: 5718463
Author: Paul J. Davis <>
Authored: Tue Nov 13 16:43:32 2012 -0600
Committer: Paul J. Davis <>
Committed: Tue Feb 4 17:03:23 2014 -0600

 src/couch_db.erl | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/couch_db.erl b/src/couch_db.erl
index 2253e62..67c8a49 100644
--- a/src/couch_db.erl
+++ b/src/couch_db.erl
@@ -682,6 +682,8 @@ prep_and_validate_replicated_updates(Db, [Bucket|RestBuckets], [OldInfo|RestOldI
             {[], AccErrors}, Bucket),
         prep_and_validate_replicated_updates(Db, RestBuckets, RestOldInfo, [ValidatedBucket
| AccPrepped], AccErrors3);
     {ok, #full_doc_info{rev_tree=OldTree}} ->
+        OldLeafs = couch_key_tree:get_all_leafs_full(OldTree),
+        OldLeafsLU = [{Start, RevId} || {Start, [{RevId, _}|_]} <- OldLeafs],
         NewRevTree = lists:foldl(
             fun({NewDoc, _Ref}, AccTree) ->
                 {NewTree, _} = couch_key_tree:merge(AccTree,
@@ -694,8 +696,9 @@ prep_and_validate_replicated_updates(Db, [Bucket|RestBuckets], [OldInfo|RestOldI
         {ValidatedBucket, AccErrors3} =
             fun({#doc{id=Id,revs={Pos, [RevId|_]}}=Doc, Ref}, {AccValidated, AccErrors2})
+                IsOldLeaf = lists:member({Pos, RevId}, OldLeafsLU),
                 case dict:find({Pos, RevId}, LeafRevsFullDict) of
-                {ok, {Start, Path}} ->
+                {ok, {Start, Path}} when not IsOldLeaf ->
                     % our unflushed doc is a leaf node. Go back on the path
                     % to find the previous rev that's on disk.

View raw message