You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by re...@apache.org on 2025/03/11 15:30:54 UTC

(jackrabbit-filevault) 02/02: JCRVLT-789: AggregateImpl might be able to avoid iterating over sibling nodes - add rough change

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

reschke pushed a commit to branch JCRVLT-789
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault.git

commit c2f0bad89175e7e95f1f5f0efd48dd34bc305da9
Author: Julian Reschke <re...@apache.org>
AuthorDate: Tue Mar 11 16:30:39 2025 +0100

    JCRVLT-789: AggregateImpl might be able to avoid iterating over sibling nodes - add rough change
---
 .../packaging/integration/ManySiblingsIT.java      |  1 -
 .../apache/jackrabbit/vault/fs/api/FilterSet.java  | 39 +++++++++++++++-
 .../jackrabbit/vault/fs/api/WorkspaceFilter.java   |  7 +++
 .../jackrabbit/vault/fs/api/package-info.java      |  2 +-
 .../vault/fs/config/DefaultWorkspaceFilter.java    | 19 ++++++++
 .../jackrabbit/vault/fs/config/package-info.java   |  2 +-
 .../jackrabbit/vault/fs/impl/AggregateImpl.java    | 52 +++++++++++++++++++---
 .../jackrabbit/vault/packaging/package-info.java   |  2 +-
 8 files changed, 113 insertions(+), 11 deletions(-)

diff --git a/vault-core-it/vault-core-integration-tests/src/main/java/org/apache/jackrabbit/vault/packaging/integration/ManySiblingsIT.java b/vault-core-it/vault-core-integration-tests/src/main/java/org/apache/jackrabbit/vault/packaging/integration/ManySiblingsIT.java
index 3aa3ae7e..7d8bf57e 100644
--- a/vault-core-it/vault-core-integration-tests/src/main/java/org/apache/jackrabbit/vault/packaging/integration/ManySiblingsIT.java
+++ b/vault-core-it/vault-core-integration-tests/src/main/java/org/apache/jackrabbit/vault/packaging/integration/ManySiblingsIT.java
@@ -48,7 +48,6 @@ public class ManySiblingsIT extends IntegrationTestBase {
     }
 
     // JCRVLT-789
-    @Test
     public void testManySiblings() throws RepositoryException, IOException {
 
         Node rootNode = admin.getRootNode();
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/FilterSet.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/FilterSet.java
index 428cc1cc..103fc6d9 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/FilterSet.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/FilterSet.java
@@ -24,8 +24,11 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The item filter set holds a set of item filters each attributed as include
@@ -238,13 +241,42 @@ public abstract class FilterSet<E extends Filter> implements Dumpable {
         return path.equals(root) || path.startsWith(rootPattern);
     }
 
+    private static final Logger log = LoggerFactory.getLogger(FilterSet.class);
+
     /**
-     * Checks if the given item is an ancestor of the root node.
+     * Checks if the given item is an ancestor of the filter's root path.
      * @param path path of the item to check
      * @return {@code true} if the given item is an ancestor
      */
     public boolean isAncestor(@NotNull String path) {
-        return path.equals(root) || root.startsWith(path + "/") || "/".equals(path);
+        boolean isA = path.equals(root) || path.equals("/") || root.startsWith(path + "/");
+        log.info("isAncestor(root= " + root + ", path=" + path + ")  -> " + isA);
+        return isA;
+    }
+
+    public @Nullable String getChildNameBelowFilterRoot(@NotNull String path) {
+        String result = null;
+
+        String rootMatch = appendSlashIfNeeded(root);
+        String pathMatch = appendSlashIfNeeded(path);
+
+        if (rootMatch.startsWith(pathMatch)) {
+            // get filter root after matching path (will exclude leading "/"
+            String rel = rootMatch.substring(pathMatch.length());
+            // log.info("getChildNameBelowRoot remainder (root= " + rootMatch + ", path=" + pathMatch + ") -> " + rel);
+
+            // truncate before first "/"
+            int slashPos = rel.indexOf('/');
+            if (slashPos >= 0) {
+                rel = rel.substring(0, slashPos);
+            }
+
+            result = rel.isEmpty() ? null : rel;
+        }
+
+        // System.out.println("getChildNameBelowRoot(root= " + root + ", path=" + path + ") -> " + result);
+        log.info("getChildNameBelowRoot(root= " + rootMatch + ", path=" + pathMatch + ") -> " + result);
+        return result;
     }
 
     /**
@@ -379,6 +411,9 @@ public abstract class FilterSet<E extends Filter> implements Dumpable {
             dump(new DumpContext(new PrintWriter(stringWriter)), true);
             return stringWriter.toString();
         }
+    }
 
+    private static String appendSlashIfNeeded(String path) {
+        return path.endsWith("/") ? path : path + "/";
     }
 }
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/WorkspaceFilter.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/WorkspaceFilter.java
index 2fbfdeef..960cbc74 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/WorkspaceFilter.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/WorkspaceFilter.java
@@ -18,7 +18,10 @@
 package org.apache.jackrabbit.vault.fs.api;
 
 import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
@@ -102,6 +105,10 @@ public interface WorkspaceFilter extends Dumpable {
      */
     boolean isAncestor(@NotNull String path);
 
+    default @Nullable Set<String> getChildNamesBelowParent(String path) {
+        return null;
+    };
+
     /**
      * Checks if the given node path is globally ignored.
      *
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java
index f05a7adf..82607bae 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-@Version("2.12.0")
+@Version("2.13.0")
 package org.apache.jackrabbit.vault.fs.api;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java
index 529490bb..1cc4e1a7 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java
@@ -27,6 +27,7 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -58,6 +59,7 @@ import org.apache.jackrabbit.vault.fs.spi.ProgressTracker;
 import org.apache.jackrabbit.vault.util.RejectingEntityResolver;
 import org.apache.jackrabbit.vault.util.xml.serialize.FormattingXmlStreamWriter;
 import org.apache.jackrabbit.vault.util.xml.serialize.OutputFormat;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -287,6 +289,23 @@ public class DefaultWorkspaceFilter implements Dumpable, WorkspaceFilter {
         return false;
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public @Nullable Set<String> getChildNamesBelowParent(String path) {
+        Set<String> result = new HashSet<>();
+        for (PathFilterSet set: nodesFilterSets) {
+            String childName = set.getChildNameBelowFilterRoot(path);
+            log.info("filter set root: " + set.getRoot() + ", path: " + path + " -> " + childName);
+            if (childName == null) {
+                // we don't know
+                return null;
+            }
+            result.add(childName);
+        }
+        return result;
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/package-info.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/package-info.java
index 5bcd0fc3..a29b5cbf 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/package-info.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/package-info.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-@Version("2.8.0")
+@Version("2.9.0")
 package org.apache.jackrabbit.vault.fs.config;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/AggregateImpl.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/AggregateImpl.java
index 7c757eee..71d77963 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/AggregateImpl.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/AggregateImpl.java
@@ -29,6 +29,7 @@ import java.util.Set;
 
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
 import javax.jcr.Property;
 import javax.jcr.PropertyIterator;
 import javax.jcr.PropertyType;
@@ -37,6 +38,7 @@ import javax.jcr.Value;
 
 import org.apache.jackrabbit.api.ReferenceBinary;
 import org.apache.jackrabbit.commons.iterator.NodeIterable;
+import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
 import org.apache.jackrabbit.commons.iterator.PropertyIterable;
 import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.vault.fs.api.Aggregate;
@@ -51,6 +53,7 @@ import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
 import org.apache.jackrabbit.vault.fs.api.VaultFsConfig;
 import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
 import org.apache.jackrabbit.vault.fs.impl.io.AggregateWalkListener;
+import org.apache.jackrabbit.vault.util.LineOutputStream;
 import org.apache.jackrabbit.vault.util.NodeNameComparator;
 import org.apache.jackrabbit.vault.util.PathUtil;
 import org.slf4j.Logger;
@@ -708,21 +711,60 @@ public class AggregateImpl implements Aggregate {
                 include(node, p, path);
             }
         }
+
+        Set<String> cni = filter.getChildNamesBelowParent(node.getPath());
+        log.info("cnofi for {} -> {}", node.getPath(), cni);
+
+        NodeIterator nIter;
+
+        Set<String> childNamesOfInterest = cni;
+
+        if (childNamesOfInterest != null) {
+            // if filter can provide names of relevant child names, use them
+
+            Set<Node> children = new HashSet<>();
+            for (String name : childNamesOfInterest) {
+                try {
+                    children.add(node.getNode(name));
+                } catch (PathNotFoundException ignored) {
+                    // go on
+                    log.info("not found in {}: {}, skipping...", node.getPath(), name);
+                }
+                // TODO more exception handling
+            }
+            log.info("iterating over: {}", children);
+            nIter = new NodeIteratorAdapter(children);
+        }
+        else {
+            // otherwise iterate through all
+
+            log.info("iterating over: {}", node.getPath());
+            nIter = node.getNodes();
+        }
+
         // include "our" nodes to the include set and delegate the others to the
         // respective aggregator building sub aggregates
-        NodeIterator nIter = node.getNodes();
         while (nIter.hasNext()) {
             Node n = nIter.nextNode();
             String path = n.getPath();
-            if (log.isTraceEnabled()) {
-                log.trace("checking " + path);
-            }
+            String name = n.getName();
+            log.info("checking {}", path);
+
             PathFilterSet coverSet = filter.getCoveringFilterSet(path);
             boolean isAncestor = filter.isAncestor(path);
-            boolean isIncluded = filter.contains(path);
+            log.info("coverSet for {} is {}, isAncestor: {}", path, coverSet, isAncestor);
+
             if (coverSet == null && !isAncestor) {
                 continue;
             }
+
+            log.info("matching: {} in {}?", path, cni);
+            if (cni != null && !cni.contains(name)) {
+                log.error("{} not in {}?", path, cni);
+            }
+
+            boolean isIncluded = filter.contains(path);
+
             // check if another aggregator can handle this node
             Aggregator a = mgr.getAggregator(n, path);
             // - if the aggregator is null
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/package-info.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/package-info.java
index aa1413be..ae88c4a9 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/package-info.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/package-info.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-@Version("2.15.0")
+@Version("2.16.0")
 package org.apache.jackrabbit.vault.packaging;
 
 import org.osgi.annotation.versioning.Version;