Author: asanso Date: Tue Jul 21 11:15:26 2015 New Revision: 1692087 URL: http://svn.apache.org/r1692087 Log: SLING-4891 - Improve MapEntries to cache searched vanity paths
Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java?rev=1692087&r1=1692086&r2=1692087&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java (original) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java Tue Jul 21 11:15:26 2015 @@ -357,6 +357,11 @@ public class CommonResourceResolverFacto public long getMaxCachedVanityPathEntries() { return this.activator.getMaxCachedVanityPathEntries(); } + + @Override + public boolean isMaxCachedVanityPathEntriesStartup() { + return this.activator.isMaxCachedVanityPathEntriesStartup(); + } @Override public int getVanityBloomFilterMaxBytes() { Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java?rev=1692087&r1=1692086&r2=1692087&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java (original) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java Tue Jul 21 11:15:26 2015 @@ -191,6 +191,13 @@ public class ResourceResolverFactoryActi description = "The maximum number of cached vanity path entries. " + "Default is -1 (no limit)") private static final String PROP_MAX_CACHED_VANITY_PATHS = "resource.resolver.vanitypath.maxEntries"; + + private static final boolean DEFAULT_MAX_CACHED_VANITY_PATHS_STARTUP = true; + @Property(boolValue = DEFAULT_MAX_CACHED_VANITY_PATHS_STARTUP, + label = "Limit the maximum number of cached vanity path entries only at startup", + description = "Limit the maximum number of cached vanity path entries only at startup" + + "Default is true") + private static final String PROP_MAX_CACHED_VANITY_PATHS_STARTUP = "resource.resolver.vanitypath.maxEntries.startup"; private static final int DEFAULT_VANITY_BLOOM_FILTER_MAX_BYTES = 1024000; @Property(longValue = DEFAULT_VANITY_BLOOM_FILTER_MAX_BYTES, @@ -284,6 +291,9 @@ public class ResourceResolverFactoryActi /** max number of cache vanity path entries */ private long maxCachedVanityPathEntries = DEFAULT_MAX_CACHED_VANITY_PATHS; + + /** limit max number of cache vanity path entries only at startup*/ + private boolean maxCachedVanityPathEntriesStartup = DEFAULT_MAX_CACHED_VANITY_PATHS_STARTUP; /** Maximum number of vanity bloom filter bytes */ private int vanityBloomFilterMaxBytes = DEFAULT_VANITY_BLOOM_FILTER_MAX_BYTES; @@ -394,6 +404,10 @@ public class ResourceResolverFactoryActi public long getMaxCachedVanityPathEntries() { return this.maxCachedVanityPathEntries; } + + public boolean isMaxCachedVanityPathEntriesStartup() { + return this.maxCachedVanityPathEntriesStartup; + } public int getVanityBloomFilterMaxBytes() { return this.vanityBloomFilterMaxBytes; @@ -503,6 +517,7 @@ public class ResourceResolverFactoryActi this.enableOptimizeAliasResolution = PropertiesUtil.toBoolean(properties.get(PROP_ENABLE_OPTIMIZE_ALIAS_RESOLUTION), DEFAULT_ENABLE_OPTIMIZE_ALIAS_RESOLUTION); this.maxCachedVanityPathEntries = PropertiesUtil.toLong(properties.get(PROP_MAX_CACHED_VANITY_PATHS), DEFAULT_MAX_CACHED_VANITY_PATHS); + this.maxCachedVanityPathEntriesStartup = PropertiesUtil.toBoolean(properties.get(PROP_MAX_CACHED_VANITY_PATHS_STARTUP), DEFAULT_MAX_CACHED_VANITY_PATHS_STARTUP); this.vanityBloomFilterMaxBytes = PropertiesUtil.toInteger(properties.get(PROP_VANITY_BLOOM_FILTER_MAX_BYTES), DEFAULT_VANITY_BLOOM_FILTER_MAX_BYTES); this.vanityPathPrecedence = PropertiesUtil.toBoolean(properties.get(PROP_VANITY_PATH_PRECEDENCE), DEFAULT_VANITY_PATH_PRECEDENCE); Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java?rev=1692087&r1=1692086&r2=1692087&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java (original) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java Tue Jul 21 11:15:26 2015 @@ -42,6 +42,8 @@ public interface MapConfigurationProvide long getMaxCachedVanityPathEntries(); + boolean isMaxCachedVanityPathEntriesStartup(); + int getVanityBloomFilterMaxBytes(); boolean isOptimizeAliasResolutionEnabled(); Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java?rev=1692087&r1=1692086&r2=1692087&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java (original) +++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java Tue Jul 21 11:15:26 2015 @@ -124,6 +124,8 @@ public class MapEntries implements Event private final long maxCachedVanityPathEntries; + private final boolean maxCachedVanityPathEntriesStartup; + private final int vanityBloomFilterMaxBytes; private final boolean enableOptimizeAliasResolution; @@ -156,6 +158,7 @@ public class MapEntries implements Event this.eventAdmin = null; this.enabledVanityPaths = true; this.maxCachedVanityPathEntries = -1; + this.maxCachedVanityPathEntriesStartup = true; this.vanityBloomFilterMaxBytes = 0; this.enableOptimizeAliasResolution = true; this.vanityPathConfig = null; @@ -172,6 +175,7 @@ public class MapEntries implements Event this.mapRoot = factory.getMapRoot(); this.enabledVanityPaths = factory.isVanityPathEnabled(); this.maxCachedVanityPathEntries = factory.getMaxCachedVanityPathEntries(); + this.maxCachedVanityPathEntriesStartup = factory.isMaxCachedVanityPathEntriesStartup(); this.vanityBloomFilterMaxBytes = factory.getVanityBloomFilterMaxBytes(); this.vanityPathConfig = factory.getVanityPathConfig(); this.enableOptimizeAliasResolution = factory.isOptimizeAliasResolutionEnabled(); @@ -853,8 +857,7 @@ public class MapEntries implements Event */ private Map<String, List<MapEntry>> getVanityPaths(String vanityPath) { - final Map<String, List<MapEntry>> entryMap = new HashMap<String, List<MapEntry>>(); - final Map <String, List<String>> targetPaths = new HashMap <String, List<String>>(); + Map<String, List<MapEntry>> entryMap = new HashMap<String, List<MapEntry>>(); // sling:VanityPath (uppercase V) is the mixin name // sling:vanityPath (lowercase) is the property name @@ -868,7 +871,14 @@ public class MapEntries implements Event final Iterator<Resource> i = queryResolver.findResources(queryString, "sql"); while (i.hasNext()) { final Resource resource = i.next(); - loadVanityPath(resource, entryMap, targetPaths, true, false); + if (maxCachedVanityPathEntriesStartup) { + loadVanityPath(resource, resolveMapsMap, vanityTargets, true, false); + vanityCounter.incrementAndGet(); + entryMap = resolveMapsMap; + } else { + final Map <String, List<String>> targetPaths = new HashMap <String, List<String>>(); + loadVanityPath(resource, entryMap, targetPaths, true, false); + } } } catch (LoginException e) { log.error("Exception while obtaining queryResolver", e); Modified: sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java?rev=1692087&r1=1692086&r2=1692087&view=diff ============================================================================== --- sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java (original) +++ sling/trunk/bundles/resourceresolver/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java Tue Jul 21 11:15:26 2015 @@ -40,7 +40,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; - +import java.util.concurrent.atomic.AtomicLong; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ResourceUtil; @@ -110,6 +110,10 @@ public class MapEntriesTest { field1.setAccessible(true); field1.set(mapEntries, -1); + Field field2 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntriesStartup"); + field2.setAccessible(true); + field2.set(mapEntries, true); + } @After @@ -1368,4 +1372,104 @@ public class MapEntriesTest { Boolean resfreshed = (Boolean ) method.invoke(mapEntries, "/node", true); assertTrue(resfreshed.booleanValue()); } + + @Test + //SLING-4891 + public void test_getVanityPaths_1() throws Exception { + + Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries"); + field1.setAccessible(true); + field1.set(mapEntries, 10); + + Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class); + method.setAccessible(true); + method.invoke(mapEntries, "/notExisting"); + + Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); + vanityCounter.setAccessible(true); + AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); + assertEquals(0, counter.longValue()); + } + + @Test + //SLING-4891 + public void test_getVanityPaths_2() throws Exception { + + Resource parent = mock(Resource.class); + when(parent.getPath()).thenReturn("/parent"); + final Resource result = mock(Resource.class); + + when(result.getParent()).thenReturn(parent); + when(result.getPath()).thenReturn("/parent/child"); + when(result.getName()).thenReturn("child"); + when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "vanity")); + + + when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { + + public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { + if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { + return Collections.singleton(result).iterator(); + } else { + return Collections.<Resource> emptySet().iterator(); + } + } + }); + + Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries"); + field1.setAccessible(true); + field1.set(mapEntries, 10); + + Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class); + method.setAccessible(true); + method.invoke(mapEntries, "/existing"); + + Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); + vanityCounter.setAccessible(true); + AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); + assertEquals(1, counter.longValue()); + } + + @Test + //SLING-4891 + public void test_getVanityPaths_3() throws Exception { + + Resource parent = mock(Resource.class); + when(parent.getPath()).thenReturn("/parent"); + final Resource result = mock(Resource.class); + + when(result.getParent()).thenReturn(parent); + when(result.getPath()).thenReturn("/parent/child"); + when(result.getName()).thenReturn("child"); + when(result.adaptTo(ValueMap.class)).thenReturn(buildValueMap("sling:vanityPath", "vanity")); + + + when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { + + public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { + if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { + return Collections.singleton(result).iterator(); + } else { + return Collections.<Resource> emptySet().iterator(); + } + } + }); + + Field field1 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntries"); + field1.setAccessible(true); + field1.set(mapEntries, 10); + + Field field2 = MapEntries.class.getDeclaredField("maxCachedVanityPathEntriesStartup"); + field2.setAccessible(true); + field2.set(mapEntries, false); + + Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class); + method.setAccessible(true); + method.invoke(mapEntries, "/existing"); + + Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); + vanityCounter.setAccessible(true); + AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); + assertEquals(0, counter.longValue()); + } }