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 mr...@apache.org on 2016/12/14 16:53:25 UTC

svn commit: r1774292 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImpl.java test/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImplTest.java

Author: mreutegg
Date: Wed Dec 14 16:53:25 2016
New Revision: 1774292

URL: http://svn.apache.org/viewvc?rev=1774292&view=rev
Log:
OAK-5186: ChangeSetFilterImpl: support many includePaths by filtering for 1st path name

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImpl.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImplTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImpl.java?rev=1774292&r1=1774291&r2=1774292&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImpl.java Wed Dec 14 16:53:25 2016
@@ -42,6 +42,7 @@ public class ChangeSetFilterImpl impleme
     private static final int MAX_EXCLUDE_PATH_CUTOFF_LEVEL = 6;
     
     private final Set<String> rootIncludePaths;
+    private final Set<String> firstLevelIncludeNames;
     private final Set<Pattern> includePathPatterns;
     private final Set<Pattern> excludePathPatterns;
     private final Set<Pattern> unpreciseExcludePathPatterns;
@@ -69,6 +70,7 @@ public class ChangeSetFilterImpl impleme
             int maxExcludedPaths) {
         this.rootIncludePaths = new HashSet<String>();
         this.includePathPatterns = new HashSet<Pattern>();
+        Set<String> firstLevelIncludePaths = new HashSet<String>();
         for (String aRawIncludePath : includedParentPaths) {
             final String aGlobbingIncludePath;
             if (aRawIncludePath.contains("*")) {
@@ -79,13 +81,31 @@ public class ChangeSetFilterImpl impleme
             }
             this.rootIncludePaths.add(aRawIncludePath);
             this.includePathPatterns.add(asPattern(aGlobbingIncludePath));
+            if (firstLevelIncludePaths != null) {
+                final String firstLevelName = firstLevelName(aRawIncludePath);
+                if (firstLevelName != null && !firstLevelName.contains("*")) {
+                    firstLevelIncludePaths.add(firstLevelName);
+                } else {
+                    firstLevelIncludePaths = null;
+                }
+            }
         }
         if (additionalIncludedParentPaths != null) {
             for (String path : additionalIncludedParentPaths) {
                 this.rootIncludePaths.add(path);
                 this.includePathPatterns.add(asPattern(path));
+                if (firstLevelIncludePaths != null) {
+                    final String firstLevelName = firstLevelName(path);
+                    if (firstLevelName != null && !firstLevelName.contains("*")) {
+                        firstLevelIncludePaths.add(firstLevelName);
+                    } else {
+                        firstLevelIncludePaths = null;
+                    }
+                }
             }
         }
+        this.firstLevelIncludeNames = firstLevelIncludePaths;
+        
         // OAK-5169:
         // excludedParentPaths could in theory be a large list, in which case
         // the excludes() algorithm becomes non-performing. Reason is, that it
@@ -119,6 +139,18 @@ public class ChangeSetFilterImpl impleme
         this.parentNodeNames = parentNodeNames == null ? null : new HashSet<String>(parentNodeNames);
     }
     
+    private String firstLevelName(String path) {
+        if (path.isEmpty() || path.equals("/")) {
+            return null;
+        }
+        int secondSlash = path.indexOf("/", 1);
+        if (secondSlash != -1) {
+            return path.substring(1, secondSlash);
+        } else {
+            return path.substring(1);
+        }
+    }
+
     private Set<String> unprecisePaths(Set<String> paths, int maxExcludedPaths, int maxExcludePathCutOffLevel) {
         int level = maxExcludePathCutOffLevel;
         while(level > 1) {
@@ -228,6 +260,15 @@ public class ChangeSetFilterImpl impleme
                 included = true;
                 break;
             }
+            if (firstLevelIncludeNames != null) {
+                final String firstLevelName = firstLevelName(aPath);
+                if (firstLevelName != null && !firstLevelIncludeNames.contains(firstLevelName)) {
+                    // then the 'first level name check' concluded that
+                    // it's not in any include path - hence we can skip
+                    // the (more expensive) pattern check
+                    continue;
+                }
+            }
             if (patternsMatch(this.includePathPatterns, aPath)) {
                 included = true;
                 break;

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImplTest.java?rev=1774292&r1=1774291&r2=1774292&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImplTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/filter/ChangeSetFilterImplTest.java Wed Dec 14 16:53:25 2016
@@ -25,13 +25,20 @@ import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Set;
 
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Sets;
+
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.plugins.observation.ChangeSet;
 import org.apache.jackrabbit.oak.plugins.observation.ChangeSetBuilder;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class ChangeSetFilterImplTest {
 
+    private static final Logger LOG = LoggerFactory.getLogger(ChangeSetFilterImplTest.class);
+
     /** shortcut for creating a set of strings */
     private Set<String> s(String... entries) {
         return new HashSet<String>(Arrays.asList(entries));
@@ -332,4 +339,36 @@ public class ChangeSetFilterImplTest {
             assertFalse(prefilter.excludes(builder.build()));
         }
     }
+
+    @Test
+    public void manyIncludePaths() throws Exception {
+        int numPaths = 50;
+        ChangeSetBuilder builder = newBuilder(50, 9);
+        for (int i = 0; i < numPaths; i++) {
+            builder.addParentPath("/a/b/c/d/e/n" + i);
+        }
+        ChangeSet cs = builder.build();
+
+        Set<String> includes = Sets.newHashSet();
+        for (int i = 0; i < 100; i++) {
+            includes.add("/foo/bar/n-" + i + "/*.jsp");
+        }
+        ChangeSetFilter filter = new ChangeSetFilterImpl(s(),true,
+                includes, s(), s(), s(), s());
+
+        // warm up
+        doManyIncludePaths(filter, cs);
+
+        // and measure
+        Stopwatch sw = Stopwatch.createStarted();
+        doManyIncludePaths(filter, cs);
+        LOG.info("manyIncludePaths() took {}", sw.stop());
+    }
+
+    private void doManyIncludePaths(ChangeSetFilter filter, ChangeSet cs)
+            throws Exception {
+        for (int i = 0; i < 20000; i++) {
+            assertTrue(filter.excludes(cs));
+        }
+    }
 }