You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by re...@apache.org on 2024/02/23 17:22:27 UTC

(jackrabbit-oak) branch OAK-10660 created (now ce276e3c18)

This is an automated email from the ASF dual-hosted git repository.

reschke pushed a change to branch OAK-10660
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git


      at ce276e3c18 OAK-10660: DocumentNodeStore: avoid repeated commits of :childOrder in branch commits

This branch includes the following new commits:

     new ce276e3c18 OAK-10660: DocumentNodeStore: avoid repeated commits of :childOrder in branch commits

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(jackrabbit-oak) 01/01: OAK-10660: DocumentNodeStore: avoid repeated commits of :childOrder in branch commits

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reschke pushed a commit to branch OAK-10660
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit ce276e3c18eaf9d3b473a6bcfb1e887e2e7d3cef
Author: Julian Reschke <re...@apache.org>
AuthorDate: Fri Feb 23 18:22:05 2024 +0100

    OAK-10660: DocumentNodeStore: avoid repeated commits of :childOrder in branch commits
---
 .../apache/jackrabbit/oak/jcr/ManyChildrenIT.java  |  6 ++--
 .../jackrabbit/oak/plugins/document/Commit.java    | 42 +++++++++++++++++-----
 .../plugins/document/DocumentNodeStoreBranch.java  |  6 +++-
 3 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ManyChildrenIT.java b/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ManyChildrenIT.java
index eeac7c5cc8..dc56586904 100644
--- a/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ManyChildrenIT.java
+++ b/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ManyChildrenIT.java
@@ -82,7 +82,7 @@ public class ManyChildrenIT extends AbstractRepositoryTest {
     }
 
     @Test
-    @Ignore //OAK-10646
+    // @Ignore //OAK-10646
     public void orderableAddManyChildrenWithSave() throws Exception {
         int childCount = 1000;
         StringBuilder prefix = new StringBuilder("");
@@ -98,7 +98,7 @@ public class ManyChildrenIT extends AbstractRepositoryTest {
     }
 
     @Test
-    @Ignore //OAK-10646
+    // @Ignore //OAK-10646
     public void moveOrderableWithManyChildren() throws Exception {
         int childCount = 1000;
         int moveCount = 1;
@@ -121,7 +121,7 @@ public class ManyChildrenIT extends AbstractRepositoryTest {
     }
 
     @Test
-    @Ignore //OAK-10646
+    // @Ignore //OAK-10646
     public void copyOrderableWithManyChildren() throws Exception {
         int childCount = 1000;
         int copyCount = 1;
diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
index a22e8adb1d..8963692360 100644
--- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
+++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
@@ -32,6 +32,8 @@ import org.apache.jackrabbit.guava.common.collect.Iterables;
 import org.apache.jackrabbit.guava.common.collect.Sets;
 import org.apache.jackrabbit.oak.commons.json.JsopStream;
 import org.apache.jackrabbit.oak.commons.json.JsopWriter;
+import org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key;
+import org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation;
 import org.apache.jackrabbit.oak.plugins.document.util.Utils;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -192,13 +194,17 @@ public class Commit {
         return success;
     }
 
+    void apply() throws ConflictException, DocumentStoreException {
+        apply(Collections.emptySet());
+    }
+
     /**
      * Applies this commit to the store.
      *
      * @throws ConflictException if the commit failed because of a conflict.
      * @throws DocumentStoreException if the commit cannot be applied.
      */
-    void apply() throws ConflictException, DocumentStoreException {
+    void apply(Set<Revision> previousRevisions) throws ConflictException, DocumentStoreException {
         boolean success = false;
         RevisionVector baseRev = getBaseRevision();
         boolean isBranch = baseRev != null && baseRev.isBranch();
@@ -206,7 +212,7 @@ public class Commit {
         if (isBranch && !nodeStore.isDisableBranches()) {
             try {
                 // prepare commit
-                prepare(baseRev);
+                prepare(baseRev, previousRevisions);
                 success = true;
             } finally {
                 if (!success) {
@@ -237,12 +243,12 @@ public class Commit {
         }
     }
 
-    private void prepare(RevisionVector baseRevision)
+    private void prepare(RevisionVector baseRevision, Set<Revision> previousRevisions)
             throws ConflictException, DocumentStoreException {
         if (!operations.isEmpty()) {
             updateParentChildStatus();
             updateBinaryStatus();
-            applyToDocumentStoreWithTiming(baseRevision);
+            applyToDocumentStoreWithTiming(baseRevision, previousRevisions);
         }
     }
 
@@ -259,7 +265,7 @@ public class Commit {
      * Apply the changes to the document store.
      */
     void applyToDocumentStore() throws ConflictException, DocumentStoreException {
-        applyToDocumentStoreWithTiming(null);
+        applyToDocumentStoreWithTiming(null, Collections.emptySet());
     }
 
     /**
@@ -271,11 +277,11 @@ public class Commit {
      * @throws DocumentStoreException if an error occurs while writing to the
      *          underlying store.
      */
-    private void applyToDocumentStoreWithTiming(RevisionVector baseBranchRevision)
+    private void applyToDocumentStoreWithTiming(RevisionVector baseBranchRevision, Set<Revision> previousRevisions)
             throws ConflictException, DocumentStoreException {
         long start = System.nanoTime();
         try {
-            applyToDocumentStore(baseBranchRevision);
+            applyToDocumentStore(baseBranchRevision, previousRevisions);
         } finally {
             nodeStore.getStatsCollector().doneChangesApplied(
                     TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - start));
@@ -291,7 +297,7 @@ public class Commit {
      * @throws DocumentStoreException if an error occurs while writing to the
      *          underlying store.
      */
-    private void applyToDocumentStore(RevisionVector baseBranchRevision)
+    private void applyToDocumentStore(RevisionVector baseBranchRevision, Set<Revision> previousRevisions)
             throws ConflictException, DocumentStoreException {
         // initially set the rollback to always fail until we have changes
         // in an oplog list and a commit root.
@@ -354,7 +360,27 @@ public class Commit {
         boolean commitRootHasChanges = operations.containsKey(commitRootPath);
         for (UpdateOp op : operations.values()) {
             NodeDocument.setCommitRoot(op, revision, commitRootDepth);
+
+            // special case for :childOrder updates
+            if (!previousRevisions.isEmpty()) {
+                boolean removePreviousSetOperations = false;
+                for (Map.Entry<Key, Operation> change : op.getChanges().entrySet()) {
+                    if (":childOrder".equals(change.getKey().getName()) && Operation.Type.SET_MAP_ENTRY == change.getValue().type) {
+                        // we are setting child order, so we should remove previous set operations from the same branch
+                        removePreviousSetOperations= true;
+                    }
+                }
+
+                if (removePreviousSetOperations) {
+                    for (Revision rev : previousRevisions) {
+                        op.removeMapEntry(":childOrder", rev);
+                    }
+                    LOG.debug("edited op is: " + op);
+                }
+            }
+
             changedNodes.add(op);
+
         }
         // create a "root of the commit" if there is none
         UpdateOp commitRoot = getUpdateOperationForNode(commitRootPath);
diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java
index 1b04f62fa5..ce010469c5 100644
--- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java
+++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java
@@ -78,6 +78,9 @@ class DocumentNodeStoreBranch implements NodeStoreBranch {
     /** The maximum number of updates to keep in memory */
     private final int updateLimit;
 
+    /** Revisions created for this branch */
+    private final Set<Revision> revisions = new HashSet<>();
+
     /**
      * State of the this branch. Either {@link Unmodified}, {@link InMemory}, {@link Persisted},
      * {@link ResetFailed} or {@link Merged}.
@@ -318,9 +321,10 @@ class DocumentNodeStoreBranch implements NodeStoreBranch {
                 // finally clause cancel the commit
                 return base;
             }
-            c.apply();
+            c.apply(revisions);
             rev = store.done(c, base.getRootRevision().isBranch(), info);
             success = true;
+            revisions.add(c.getRevision());
         } finally {
             if (!success) {
                 store.canceled(c);