couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject [25/50] git commit: Assume success when we replicate an existing leaf
Date Sat, 18 Jan 2014 00:47:50 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/heads/import
Commit: bd7e7e8f17dff8cb4671062d7b1167013d1231bd
Parents: e3ee94c
Author: Paul J. Davis <>
Authored: Tue Nov 13 16:43:32 2012 -0600
Committer: Paul J. Davis <>
Committed: Fri Jan 17 16:44:30 2014 -0800

 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