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 st...@apache.org on 2024/03/27 17:38:26 UTC

(jackrabbit-oak) 01/01: OAK-10728 : embedded verification fails if id is from long path

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

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

commit 06faf74f473c69aa86adc15e31f8cee7454ee2c2
Author: Stefan Egli <st...@apache.org>
AuthorDate: Wed Mar 27 18:38:14 2024 +0100

    OAK-10728 : embedded verification fails if id is from long path
---
 .../oak/plugins/document/VersionGarbageCollector.java   | 17 ++++++++++++++++-
 .../oak/plugins/document/VersionGarbageCollectorIT.java | 11 +++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java
index 11933267a2..1f937591f1 100644
--- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java
+++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java
@@ -933,6 +933,9 @@ public class VersionGarbageCollector {
         /** contains the list of _ids of orphan or deleted documents to be removed in the current batch **/
         private final Map<String, Long> orphanOrDeletedRemovalMap;
 
+        /** contains the list of _ids of orphan or deleted documents to be removed, mapped to their path */
+        private final Map<String, Path> orphanOrDeletedRemovalPathMap;
+
         /**
          * Map of documentId => total no. of deleted properties.
          * <p>
@@ -977,6 +980,7 @@ public class VersionGarbageCollector {
             this.cancel = cancel;
             this.updateOpList = new ArrayList<>();
             this.orphanOrDeletedRemovalMap = new HashMap<>();
+            this.orphanOrDeletedRemovalPathMap = new HashMap<>();
             this.deletedPropsCountMap = new HashMap<>();
             this.deletedInternalPropsCountMap = new HashMap<>();
             this.deletedPropRevsCountMap = new HashMap<>();
@@ -1009,6 +1013,7 @@ public class VersionGarbageCollector {
                 totalGarbageDocsCount++;
                 monitor.info("Deleted orphaned or deleted doc [{}]", doc.getId());
                 orphanOrDeletedRemovalMap.put(doc.getId(), doc.getModified());
+                orphanOrDeletedRemovalPathMap.put(doc.getId(), doc.getPath());
             } else {
                 // here the node is not orphaned which means that we can reach the node from root
                 collectDeletedProperties(doc, phases, op, traversedState);
@@ -1674,7 +1679,16 @@ public class VersionGarbageCollector {
                     };
                     for (Entry<String, Long> e : orphanOrDeletedRemovalMap.entrySet()) {
                         NodeState traversedState = root;
-                        for (String name : Path.fromString(Utils.getPathFromId(e.getKey())).elements()) {
+                        final String id = e.getKey();
+                        final Path path = orphanOrDeletedRemovalPathMap.get(id);
+                        if (path == null) {
+                            // rather a bug, so let's skip it
+                            log.error("removeGarbage.verify : no path available for id : {}", id);
+                            it.remove();
+                            stats.skippedDetailedGCDocsCount++;
+                            continue;
+                        }
+                        for (String name : path.elements()) {
                             traversedState = traversedState.getChildNode(name);
                         }
                         if (!verifyDeletion(traversedState)) {
@@ -1743,6 +1757,7 @@ public class VersionGarbageCollector {
                 // now reset delete metadata
                 updateOpList.clear();
                 orphanOrDeletedRemovalMap.clear();
+                orphanOrDeletedRemovalPathMap.clear();
                 deletedPropsCountMap.clear();
                 deletedInternalPropsCountMap.clear();
                 deletedPropRevsCountMap.clear();
diff --git a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollectorIT.java b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollectorIT.java
index 854ad7b69b..f249d111b9 100644
--- a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollectorIT.java
+++ b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollectorIT.java
@@ -1520,6 +1520,17 @@ public class VersionGarbageCollectorIT {
         doLateWriteCreateChildrenGC(of("/a", "/a/b/c"), of("/a/b/c/d", "/a/b/c/d/e/f"), 3, "/d");
     }
 
+    /**
+     * Same as {@link #lateWriteCreateChildGC()} except with a long path
+     * (where the id becomes a hash)
+     */
+    @Test
+    public void lateWriteCreateChildGCLargePath() throws Exception {
+        String longPath = repeat("p", PATH_LONG + 1);
+        String path = "/grand/parent/" + longPath + "/longPathChild";
+        doLateWriteCreateChildrenGC(of("/grand/parent"), of(path), 2, "/d");
+    }
+
     /**
      * Tests whether DetailedGC can delete a large amount of randomly
      * created orphans (that were added in a late-write manner)