Author: tomekr
Date: Wed Jul 26 09:19:26 2017
New Revision: 1803029

URL: http://svn.apache.org/viewvc?rev=1803029&view=rev
Log:
OAK-6486: NPE in CompositeNodeStore

Replaced the CopyOnReadIdentityMap with a Function<MountedNodeStore, NodeState>

Added:
    
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/util/
    
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/util/Memoizer.java
Removed:
    
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CopyOnReadIdentityMap.java
Modified:
    
jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreTest.java
    
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CommitHookEnhancer.java
    
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java
    
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeState.java
    
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStore.java
    
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositionContext.java

Modified: 
jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreTest.java?rev=1803029&r1=1803028&r2=1803029&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreTest.java
 Wed Jul 26 09:19:26 2017
@@ -82,7 +82,6 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;

Modified: 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CommitHookEnhancer.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CommitHookEnhancer.java?rev=1803029&r1=1803028&r2=1803029&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CommitHookEnhancer.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CommitHookEnhancer.java
 Wed Jul 26 09:19:26 2017
@@ -20,7 +20,6 @@ import org.apache.jackrabbit.oak.api.Com
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.state.ApplyDiff;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
 import javax.annotation.Nonnull;
@@ -33,15 +32,15 @@ class CommitHookEnhancer implements Comm
 
     private final CompositionContext ctx;
 
-    private final Map<MountedNodeStore, NodeBuilder> builders;
+    private final CompositeNodeBuilder builder;
 
     private final CommitHook hook;
 
     private Optional<CompositeNodeBuilder> updatedBuilder = Optional.empty();
 
-    CommitHookEnhancer(CommitHook hook, CompositionContext ctx, 
Map<MountedNodeStore, NodeBuilder> builders) {
+    CommitHookEnhancer(CommitHook hook, CompositionContext ctx, 
CompositeNodeBuilder builder) {
         this.ctx = ctx;
-        this.builders = builders;
+        this.builder = builder;
         this.hook = hook;
     }
 
@@ -51,8 +50,8 @@ class CommitHookEnhancer implements Comm
         Map<MountedNodeStore, NodeState> beforeStates = newHashMap();
         Map<MountedNodeStore, NodeState> afterStates = newHashMap();
         for (MountedNodeStore mns : ctx.getNonDefaultStores()) {
-            afterStates.put(mns, mns.getNodeStore().rebase(builders.get(mns)));
-            beforeStates.put(mns, builders.get(mns).getBaseState());
+            afterStates.put(mns, 
mns.getNodeStore().rebase(builder.getNodeBuilder(mns)));
+            beforeStates.put(mns, builder.getNodeBuilder(mns).getBaseState());
         }
         afterStates.put(ctx.getGlobalStore(), after);
         beforeStates.put(ctx.getGlobalStore(), before);

Modified: 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java?rev=1803029&r1=1803028&r2=1803029&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java
 Wed Jul 26 09:19:26 2017
@@ -16,43 +16,47 @@
  */
 package org.apache.jackrabbit.oak.composite;
 
-import com.google.common.base.Function;
 import com.google.common.base.Objects;
-import com.google.common.collect.Maps;
+import com.google.common.collect.FluentIterable;
 import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.composite.util.Memoizer;
 import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
 import org.apache.jackrabbit.oak.spi.state.MoveDetector;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Iterables.concat;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.transform;
-import static com.google.common.collect.Maps.transformValues;
+import static com.google.common.collect.Maps.newHashMap;
 import static java.lang.Long.MAX_VALUE;
 import static java.util.Collections.singleton;
+import static 
org.apache.jackrabbit.oak.composite.CompositeNodeState.STOP_COUNTING_CHILDREN;
+import static 
org.apache.jackrabbit.oak.composite.CompositeNodeState.accumulateChildSizes;
+import static 
org.apache.jackrabbit.oak.composite.CompositeNodeState.wrapWithNullCheck;
 import static 
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.MISSING_NODE;
 import static 
org.apache.jackrabbit.oak.spi.state.AbstractNodeState.checkValidName;
 
 class CompositeNodeBuilder implements NodeBuilder {
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(CompositeNodeBuilder.class);
+
     private final String path;
 
     private final CompositionContext ctx;
 
-    private Map<MountedNodeStore, NodeBuilder> nodeBuilders;
+    private Function<MountedNodeStore, NodeBuilder> nodeBuilders;
 
     private final MountedNodeStore owningStore;
 
@@ -60,15 +64,14 @@ class CompositeNodeBuilder implements No
 
     private final CompositeNodeBuilder rootBuilder;
 
-    CompositeNodeBuilder(String path, Map<MountedNodeStore, NodeBuilder> 
nodeBuilders, CompositionContext ctx) {
+    CompositeNodeBuilder(String path, Function<MountedNodeStore, NodeBuilder> 
nodeBuilders, CompositionContext ctx) {
         this(path, nodeBuilders, ctx, null);
     }
 
-    private CompositeNodeBuilder(String path, Map<MountedNodeStore, 
NodeBuilder> nodeBuilders, CompositionContext ctx, CompositeNodeBuilder parent) 
{
-        checkArgument(nodeBuilders.size() == ctx.getStoresCount(), "Got %s 
builders but the context manages %s stores", nodeBuilders.size(), 
ctx.getStoresCount());
+    private CompositeNodeBuilder(String path, Function<MountedNodeStore, 
NodeBuilder> nodeBuilders, CompositionContext ctx, CompositeNodeBuilder parent) 
{
         this.path = path;
         this.ctx = ctx;
-        this.nodeBuilders = new CopyOnReadIdentityMap<>(nodeBuilders);
+        this.nodeBuilders = wrapWithNullCheck(Memoizer.memoize(nodeBuilders), 
LOG, path);
         this.owningStore = ctx.getOwningStore(path);
         this.parent = parent;
         if (parent == null) {
@@ -78,40 +81,24 @@ class CompositeNodeBuilder implements No
         }
     }
 
-    Map<MountedNodeStore, NodeBuilder> getBuilders() {
-        return nodeBuilders;
+    NodeBuilder getNodeBuilder(MountedNodeStore mns) {
+        return nodeBuilders.apply(mns);
     }
 
     @Override
     public CompositeNodeState getNodeState() {
-        return new CompositeNodeState(path, 
buildersToNodeStates(nodeBuilders), ctx);
+        Map<MountedNodeStore, NodeState> states = 
ctx.getAllMountedNodeStores().stream().collect(Collectors.toMap(Function.identity(),
+                nodeBuilders
+                        .andThen(n -> n.exists() ? n.getNodeState() : 
MISSING_NODE)));
+        return new CompositeNodeState(path, states, ctx);
     }
 
     @Override
     public CompositeNodeState getBaseState() {
-        return new CompositeNodeState(path, 
buildersToBaseStates(nodeBuilders), ctx);
-    }
-
-    private static Map<MountedNodeStore, NodeState> 
buildersToNodeStates(Map<MountedNodeStore, NodeBuilder> builders) {
-        return new IdentityHashMap<>(transformValues(builders, new 
Function<NodeBuilder, NodeState>() {
-            @Override
-            public NodeState apply(NodeBuilder input) {
-                if (input.exists()) {
-                    return input.getNodeState();
-                } else {
-                    return MISSING_NODE;
-                }
-            }
-        }));
-    }
-
-    private static Map<MountedNodeStore, NodeState> 
buildersToBaseStates(Map<MountedNodeStore, NodeBuilder> builders) {
-        return new IdentityHashMap<>(transformValues(builders, new 
Function<NodeBuilder, NodeState>() {
-            @Override
-            public NodeState apply(NodeBuilder input) {
-                return input.getBaseState();
-            }
-        }));
+        Map<MountedNodeStore, NodeState> states = 
ctx.getAllMountedNodeStores().stream().collect(Collectors.toMap(Function.identity(),
+                nodeBuilders
+                        .andThen(NodeBuilder::getBaseState)));
+        return new CompositeNodeState(path, states, ctx);
     }
 
     // node or property-related methods ; directly delegate to wrapped builder
@@ -219,35 +206,31 @@ class CompositeNodeBuilder implements No
             return getWrappedNodeBuilder().getChildNodeCount(max);
         } else {
             // Count the children in each contributing store.
-            return 
CompositeNodeState.accumulateChildSizes(concat(transform(contributingStores, 
new Function<MountedNodeStore, Iterable<String>>() {
-                @Override
-                public Iterable<String> apply(MountedNodeStore input) {
-                    NodeBuilder contributing = nodeBuilders.get(input);
-                    if (contributing.getChildNodeCount(max) == MAX_VALUE) {
-                        return 
singleton(CompositeNodeState.STOP_COUNTING_CHILDREN);
-                    } else {
-                        return filter(contributing.getChildNodeNames(), 
ctx.belongsToStore(input, path));
-                    }
-                }
-            })), max);
+            return accumulateChildSizes(FluentIterable.from(contributingStores)
+                    .transformAndConcat(mns -> {
+                        NodeBuilder node = nodeBuilders.apply(mns);
+                        if (node.getChildNodeCount(max) == MAX_VALUE) {
+                            return singleton(STOP_COUNTING_CHILDREN);
+                        } else {
+                            return 
FluentIterable.from(node.getChildNodeNames()).filter(e -> belongsToStore(mns, 
e));
+                        }
+                    }), max);
         }
     }
 
     @Override
     public Iterable<String> getChildNodeNames() {
-        return concat(transform(ctx.getContributingStoresForBuilders(path, 
nodeBuilders), new Function<MountedNodeStore, Iterable<String>>() {
-            @Override
-            public Iterable<String> apply(final MountedNodeStore 
mountedNodeStore) {
-                return 
filter(nodeBuilders.get(mountedNodeStore).getChildNodeNames(), 
ctx.belongsToStore(mountedNodeStore, path));
-            }
-        }));
+        return FluentIterable.from(ctx.getContributingStoresForBuilders(path, 
nodeBuilders))
+                .transformAndConcat(mns -> FluentIterable
+                        .from(nodeBuilders.apply(mns).getChildNodeNames())
+                        .filter(e -> belongsToStore(mns, e)));
     }
 
     @Override
     public boolean hasChildNode(String name) {
         String childPath = simpleConcat(path, name);
         MountedNodeStore mountedStore = ctx.getOwningStore(childPath);
-        return nodeBuilders.get(mountedStore).hasChildNode(name);
+        return nodeBuilders.apply(mountedStore).hasChildNode(name);
     }
 
     @Override
@@ -260,29 +243,24 @@ class CompositeNodeBuilder implements No
     }
 
     private void createAncestors(MountedNodeStore mountedNodeStore) {
-        NodeBuilder builder = rootBuilder.nodeBuilders.get(mountedNodeStore);
+        NodeBuilder builder = rootBuilder.nodeBuilders.apply(mountedNodeStore);
         for (String element : PathUtils.elements(path)) {
             builder = builder.child(element);
         }
-        if (nodeBuilders instanceof CopyOnReadIdentityMap) {
-            nodeBuilders = new IdentityHashMap<>(nodeBuilders);
-        }
-        nodeBuilders.put(mountedNodeStore, builder);
+
+        // the nodeBuilders function should be updated, to return the new node 
builder
+        Map<MountedNodeStore, NodeBuilder> map = 
newHashMap(ctx.getAllMountedNodeStores().stream().collect(Collectors.toMap(Function.identity(),
 nodeBuilders)));
+        map.put(mountedNodeStore, builder);
+        nodeBuilders = wrapWithNullCheck(m -> map.get(m), LOG, path);
     }
 
     @Override
     public NodeBuilder getChildNode(final String name) {
         String childPath = simpleConcat(path, name);
         if (!ctx.shouldBeComposite(childPath)) {
-            return 
nodeBuilders.get(ctx.getOwningStore(childPath)).getChildNode(name);
+            return 
nodeBuilders.apply(ctx.getOwningStore(childPath)).getChildNode(name);
         }
-        Map<MountedNodeStore, NodeBuilder> newNodeBuilders = 
transformValues(nodeBuilders, new Function<NodeBuilder, NodeBuilder>() {
-            @Override
-            public NodeBuilder apply(NodeBuilder input) {
-                return input.getChildNode(name);
-            }
-        });
-        return new CompositeNodeBuilder(childPath, newNodeBuilders, ctx, this);
+        return new CompositeNodeBuilder(childPath, nodeBuilders.andThen(b -> 
b.getChildNode(name)), ctx, this);
     }
 
     @Override
@@ -295,25 +273,15 @@ class CompositeNodeBuilder implements No
         checkState(exists(), "This builder does not exist: " + 
PathUtils.getName(path));
         String childPath = simpleConcat(path, name);
         final MountedNodeStore childStore = ctx.getOwningStore(childPath);
-        if (childStore != owningStore && 
!nodeBuilders.get(childStore).exists()) {
+        if (childStore != owningStore && 
!nodeBuilders.apply(childStore).exists()) {
             createAncestors(childStore);
         }
-        final NodeBuilder childBuilder = 
nodeBuilders.get(childStore).setChildNode(name, nodeState);
+        final NodeBuilder childBuilder = 
nodeBuilders.apply(childStore).setChildNode(name, nodeState);
         if (!ctx.shouldBeComposite(childPath)) {
             return childBuilder;
         }
 
-        Map<MountedNodeStore, NodeBuilder> newNodeBuilders = 
Maps.transformEntries(nodeBuilders, new Maps.EntryTransformer<MountedNodeStore, 
NodeBuilder, NodeBuilder>() {
-            @Override
-            public NodeBuilder transformEntry(MountedNodeStore key, 
NodeBuilder value) {
-                if (key == childStore) {
-                    return childBuilder;
-                } else {
-                    return value.getChildNode(name);
-                }
-            }
-        });
-        return new CompositeNodeBuilder(childPath, newNodeBuilders, ctx, this);
+        return new CompositeNodeBuilder(childPath, m -> m == childStore ? 
childBuilder : nodeBuilders.apply(m).getChildNode(name), ctx, this);
     }
 
     @Override
@@ -346,7 +314,7 @@ class CompositeNodeBuilder implements No
     }
 
     private NodeBuilder getWrappedNodeBuilder() {
-        return nodeBuilders.get(owningStore);
+        return nodeBuilders.apply (owningStore);
     }
 
     private void annotateSourcePath() {
@@ -403,6 +371,10 @@ class CompositeNodeBuilder implements No
         return path;
     }
 
+    private boolean belongsToStore(MountedNodeStore mns, String childName) {
+        return ctx.belongsToStore(mns, path, childName);
+    }
+
     /**
      * This simplified version of {@link PathUtils#concat(String, String)} 
method
      * assumes that the parentPath is valid and not null, while the second 
argument

Modified: 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeState.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeState.java?rev=1803029&r1=1803028&r2=1803029&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeState.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeState.java
 Wed Jul 26 09:19:26 2017
@@ -18,13 +18,13 @@
  */
 package org.apache.jackrabbit.oak.composite;
 
-import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.composite.util.Memoizer;
 import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
 import org.slf4j.Logger;
@@ -32,18 +32,12 @@ import org.slf4j.LoggerFactory;
 
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Predicate;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Predicates.compose;
-import static com.google.common.collect.Iterables.concat;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.transform;
-import static com.google.common.collect.Maps.asMap;
-import static com.google.common.collect.Maps.transformValues;
 import static java.lang.Long.MAX_VALUE;
 import static java.util.Collections.singleton;
 import static 
org.apache.jackrabbit.oak.composite.CompositeNodeBuilder.simpleConcat;
-import static org.apache.jackrabbit.oak.spi.state.ChildNodeEntry.GET_NAME;
 
 class CompositeNodeState extends AbstractNodeState {
 
@@ -70,25 +64,36 @@ class CompositeNodeState extends Abstrac
 
     private final MountedNodeStore owningStore;
 
-    private final Map<MountedNodeStore, NodeState> nodeStates;
+    private final Function<MountedNodeStore, NodeState> nodeStates;
 
     CompositeNodeState(String path, Map<MountedNodeStore, NodeState> 
nodeStates, CompositionContext ctx) {
-        checkArgument(nodeStates.size() == ctx.getStoresCount(), "Got %s node 
states but the context manages %s stores", nodeStates.size(), 
ctx.getStoresCount());
         this.path = path;
         this.ctx = ctx;
-        this.nodeStates = new CopyOnReadIdentityMap<>(nodeStates);
+        this.nodeStates = wrapWithNullCheck(mns -> nodeStates.get(mns), LOG, 
path);
         this.owningStore = ctx.getOwningStore(path);
     }
 
-    NodeState getNodeState(MountedNodeStore mns) {
-        NodeState nodeState = nodeStates.get(mns);
-        if (nodeState != null) {
+    CompositeNodeState(String path, Function<MountedNodeStore, NodeState> 
nodeStates, CompositionContext ctx) {
+        this.path = path;
+        this.ctx = ctx;
+        this.nodeStates = wrapWithNullCheck(Memoizer.memoize(nodeStates), LOG, 
path);
+        this.owningStore = ctx.getOwningStore(path);
+    }
+
+    static <N> Function<MountedNodeStore, N> 
wrapWithNullCheck(Function<MountedNodeStore, N> f, Logger log, String path) {
+        return mns -> {
+            N nodeState = f.apply(mns);
+            if (nodeState == null) {
+                // this shouldn't happen, so we need to log some more debug 
info
+                log.warn("Can't find node state for path {} and mount {}.", 
path, mns);
+                throw new IllegalStateException("Can't find the node state for 
mount " + mns);
+            }
             return nodeState;
-        }
+        };
+    }
 
-        // this shouldn't happen, so we need to log some more debug info
-        LOG.warn("Can't find node state for path {} and mount {}. The node 
state map: {}", path, mns, nodeStates);
-        throw new IllegalStateException("Can't find the node state for mount " 
+ mns);
+    NodeState getNodeState(MountedNodeStore mns) {
+        return nodeStates.apply(mns);
     }
 
     @Override
@@ -122,44 +127,37 @@ class CompositeNodeState extends Abstrac
     public boolean hasChildNode(String name) {
         String childPath = simpleConcat(path, name);
         MountedNodeStore mountedStore = ctx.getOwningStore(childPath);
-        return getNodeState(mountedStore).hasChildNode(name);
+        return nodeStates.apply(mountedStore).hasChildNode(name);
     }
 
     @Override
     public NodeState getChildNode(final String name) {
         String childPath = simpleConcat(path, name);
         if (!ctx.shouldBeComposite(childPath)) {
-            return 
getNodeState(ctx.getOwningStore(childPath)).getChildNode(name);
+            return 
nodeStates.apply(ctx.getOwningStore(childPath)).getChildNode(name);
         }
-        Map<MountedNodeStore, NodeState> newNodeStates = 
transformValues(safeGetMap(), new Function<NodeState, NodeState>() {
-            @Override
-            public NodeState apply(NodeState input) {
-                return input.getChildNode(name);
-            }
-        });
+        Function<MountedNodeStore, NodeState> newNodeStates = 
nodeStates.andThen(n -> n.getChildNode(name));
         return new CompositeNodeState(childPath, newNodeStates, ctx);
     }
 
     @Override
     public long getChildNodeCount(final long max) {
-        List<MountedNodeStore> contributingStores = 
ctx.getContributingStoresForNodes(path, safeGetMap());
+        List<MountedNodeStore> contributingStores = 
ctx.getContributingStoresForNodes(path, nodeStates);
         if (contributingStores.isEmpty()) {
             return 0; // this shouldn't happen
         } else if (contributingStores.size() == 1) {
             return getWrappedNodeState().getChildNodeCount(max);
         } else {
             // Count the children in each contributing store.
-            return accumulateChildSizes(concat(transform(contributingStores, 
new Function<MountedNodeStore, Iterable<String>>() {
-                @Override
-                public Iterable<String> apply(MountedNodeStore mns) {
-                    NodeState contributing = getNodeState(mns);
-                    if (contributing.getChildNodeCount(max) == MAX_VALUE) {
-                        return singleton(STOP_COUNTING_CHILDREN);
-                    } else {
-                        return filter(contributing.getChildNodeNames(), 
ctx.belongsToStore(mns, path));
-                    }
-                }
-            })), max);
+            return accumulateChildSizes(FluentIterable.from(contributingStores)
+                    .transformAndConcat(mns -> {
+                        NodeState node = nodeStates.apply(mns);
+                        if (node.getChildNodeCount(max) == MAX_VALUE) {
+                            return singleton(STOP_COUNTING_CHILDREN);
+                        } else {
+                            return 
FluentIterable.from(node.getChildNodeNames()).filter(e -> belongsToStore(mns, 
e));
+                        }
+                    }), max);
         }
     }
 
@@ -176,19 +174,11 @@ class CompositeNodeState extends Abstrac
 
     @Override
     public Iterable<? extends ChildNodeEntry> getChildNodeEntries() {
-        Iterable<? extends ChildNodeEntry> nativeChildren = 
concat(transform(ctx.getContributingStoresForNodes(path, safeGetMap()), new 
Function<MountedNodeStore, Iterable<? extends ChildNodeEntry>>() {
-            @Override
-            public Iterable<? extends ChildNodeEntry> apply(final 
MountedNodeStore mountedNodeStore) {
-                return 
filter(getNodeState(mountedNodeStore).getChildNodeEntries(), 
compose(ctx.belongsToStore(mountedNodeStore, path), GET_NAME));
-            }
-        }));
-        return transform(nativeChildren, new Function<ChildNodeEntry, 
ChildNodeEntry>() {
-            @Override
-            public ChildNodeEntry apply(ChildNodeEntry input) {
-                NodeState wrapped = getChildNode(input.getName());
-                return new MemoryChildNodeEntry(input.getName(), wrapped);
-            }
-        });
+        return FluentIterable.from(ctx.getContributingStoresForNodes(path, 
nodeStates))
+                .transformAndConcat(mns -> FluentIterable
+                        .from(nodeStates.apply(mns).getChildNodeNames())
+                        .filter(n -> belongsToStore(mns, n)))
+                .transform(n -> new MemoryChildNodeEntry(n, getChildNode(n)));
     }
 
     @Override
@@ -197,13 +187,13 @@ class CompositeNodeState extends Abstrac
             CompositeNodeState multiBase = (CompositeNodeState) base;
             NodeStateDiff wrappingDiff = new WrappingDiff(diff, multiBase);
             boolean full = 
getWrappedNodeState().compareAgainstBaseState(multiBase.getWrappedNodeState(), 
new ChildrenDiffFilter(wrappingDiff, owningStore, true));
-            for (MountedNodeStore mns : 
ctx.getContributingStoresForNodes(path, safeGetMap())) {
+            for (MountedNodeStore mns : 
ctx.getContributingStoresForNodes(path, nodeStates)) {
                 if (owningStore == mns) {
                     continue;
                 }
                 NodeStateDiff childrenDiffFilter = new 
ChildrenDiffFilter(wrappingDiff, mns, false);
-                NodeState contributing = getNodeState(mns);
-                NodeState contributingBase = multiBase.getNodeState(mns);
+                NodeState contributing = nodeStates.apply(mns);
+                NodeState contributingBase = multiBase.nodeStates.apply(mns);
                 full = full && 
contributing.compareAgainstBaseState(contributingBase, childrenDiffFilter);
             }
             return full;
@@ -215,21 +205,15 @@ class CompositeNodeState extends Abstrac
     // write operations
     @Override
     public CompositeNodeBuilder builder() {
-        Map<MountedNodeStore, NodeBuilder> nodeBuilders = 
transformValues(safeGetMap(), new Function<NodeState, NodeBuilder>() {
-            @Override
-            public NodeBuilder apply(NodeState input) {
-                return input.builder();
-            }
-        });
-        return new CompositeNodeBuilder(path, nodeBuilders, ctx);
+        return new CompositeNodeBuilder(path, 
nodeStates.andThen(NodeState::builder), ctx);
     }
 
     private NodeState getWrappedNodeState() {
-        return getNodeState(owningStore);
+        return nodeStates.apply(owningStore);
     }
 
-    private Map<MountedNodeStore, NodeState> safeGetMap() {
-        return asMap(ctx.getAllMountedNodeStores(), this::getNodeState);
+    private boolean belongsToStore(MountedNodeStore mns, String childName) {
+        return ctx.belongsToStore(mns, path, childName);
     }
 
     private class ChildrenDiffFilter implements NodeStateDiff {
@@ -354,5 +338,4 @@ class CompositeNodeState extends Abstrac
             return CompositeNodeState.this.getChildNode(name);
         }
     }
-
 }

Modified: 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStore.java?rev=1803029&r1=1803028&r2=1803029&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeStore.java
 Wed Jul 26 09:19:26 2017
@@ -141,8 +141,8 @@ public class CompositeNodeStore implemen
             // merge the global builder and apply the commit hooks within
             Map<MountedNodeStore, NodeState> resultStates = newHashMap();
             MountedNodeStore globalStore = ctx.getGlobalStore();
-            CommitHookEnhancer hookEnhancer = new 
CommitHookEnhancer(commitHook, ctx, nodeBuilder.getBuilders());
-            NodeState globalResult = 
globalStore.getNodeStore().merge(nodeBuilder.getBuilders().get(globalStore), 
hookEnhancer, info);
+            CommitHookEnhancer hookEnhancer = new 
CommitHookEnhancer(commitHook, ctx, nodeBuilder);
+            NodeState globalResult = 
globalStore.getNodeStore().merge(nodeBuilder.getNodeBuilder(globalStore), 
hookEnhancer, info);
             resultStates.put(globalStore, globalResult);
 
             if (!hookEnhancer.getUpdatedBuilder().isPresent()) {
@@ -154,7 +154,7 @@ public class CompositeNodeStore implemen
 
             // merge the partial builders
             for (MountedNodeStore mns : ctx.getNonDefaultStores()) {
-                NodeBuilder partialBuilder = 
updatedBuilder.getBuilders().get(mns);
+                NodeBuilder partialBuilder = 
updatedBuilder.getNodeBuilder(mns);
 
                 if (mns.getMount().isReadOnly()) {
                     assertNoChange(mns, partialBuilder);
@@ -180,7 +180,7 @@ public class CompositeNodeStore implemen
             if (!mountedNodeStore.getMount().isReadOnly()) {
                 continue;
             }
-            NodeBuilder partialBuilder = 
nodeBuilder.getBuilders().get(mountedNodeStore);
+            NodeBuilder partialBuilder = 
nodeBuilder.getNodeBuilder(mountedNodeStore);
             assertNoChange(mountedNodeStore, partialBuilder);
         }
     }
@@ -209,7 +209,7 @@ public class CompositeNodeStore implemen
         Map<MountedNodeStore, NodeState> resultStates = newHashMap();
         for (MountedNodeStore mountedNodeStore : 
ctx.getAllMountedNodeStores()) {
             NodeStore nodeStore = mountedNodeStore.getNodeStore();
-            NodeBuilder partialBuilder = 
nodeBuilder.getBuilders().get(mountedNodeStore);
+            NodeBuilder partialBuilder = 
nodeBuilder.getNodeBuilder(mountedNodeStore);
             NodeState result = nodeStore.rebase(partialBuilder);
             resultStates.put(mountedNodeStore, result);
         }
@@ -224,7 +224,7 @@ public class CompositeNodeStore implemen
         Map<MountedNodeStore, NodeState> resultStates = newHashMap();
         for (MountedNodeStore mountedNodeStore : 
ctx.getAllMountedNodeStores()) {
             NodeStore nodeStore = mountedNodeStore.getNodeStore();
-            NodeBuilder partialBuilder = 
nodeBuilder.getBuilders().get(mountedNodeStore);
+            NodeBuilder partialBuilder = 
nodeBuilder.getNodeBuilder(mountedNodeStore);
             NodeState result = nodeStore.reset(partialBuilder);
             resultStates.put(mountedNodeStore, result);
         }

Modified: 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositionContext.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositionContext.java?rev=1803029&r1=1803028&r2=1803029&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositionContext.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositionContext.java
 Wed Jul 26 09:19:26 2017
@@ -16,11 +16,7 @@
  */
 package org.apache.jackrabbit.oak.composite;
 
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
 import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.spi.mount.Mount;
@@ -35,13 +31,11 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
 
-import static com.google.common.collect.ImmutableMap.copyOf;
-import static com.google.common.collect.Iterables.concat;
-import static com.google.common.collect.Iterables.tryFind;
 import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.uniqueIndex;
-import static java.util.Collections.singleton;
 import static java.util.Collections.singletonList;
 
 class CompositionContext {
@@ -66,12 +60,7 @@ class CompositionContext {
         b.addAll(this.nonDefaultStores);
         allStores = b.build();
 
-        this.nodeStoresByMount = copyOf(uniqueIndex(allStores, new 
Function<MountedNodeStore, Mount>() {
-            @Override
-            public Mount apply(MountedNodeStore input) {
-                return input.getMount();
-            }
-        }));
+        this.nodeStoresByMount = 
allStores.stream().collect(Collectors.toMap(MountedNodeStore::getMount, 
Function.identity()));
 
     }
 
@@ -92,31 +81,18 @@ class CompositionContext {
         }
     }
 
-    List<MountedNodeStore> getContributingStoresForNodes(String path, final 
Map<MountedNodeStore, NodeState> nodeStates) {
-        return getContributingStores(path, new Function<MountedNodeStore, 
Iterable<String>>() {
-            @Override
-            public Iterable<String> apply(MountedNodeStore input) {
-                return nodeStates.get(input).getChildNodeNames();
-            }
-        });
+    List<MountedNodeStore> getContributingStoresForNodes(String path, final 
Function<MountedNodeStore, NodeState> nodeStates) {
+        return getContributingStores(path, mns -> 
nodeStates.apply(mns).getChildNodeNames());
     }
 
-    List<MountedNodeStore> getContributingStoresForBuilders(String path, final 
Map<MountedNodeStore, NodeBuilder> nodeBuilders) {
-        return getContributingStores(path, new Function<MountedNodeStore, 
Iterable<String>>() {
-            @Override
-            public Iterable<String> apply(MountedNodeStore input) {
-                return nodeBuilders.get(input).getChildNodeNames();
-            }
-        });
+    List<MountedNodeStore> getContributingStoresForBuilders(String path, final 
Function<MountedNodeStore, NodeBuilder> nodeBuilders) {
+        return getContributingStores(path, mns -> 
nodeBuilders.apply(mns).getChildNodeNames());
     }
 
     boolean shouldBeComposite(final String path) {
-        if (Iterables.tryFind(nonDefaultStores, new 
Predicate<MountedNodeStore>() {
-            @Override
-            public boolean apply(MountedNodeStore input) {
-                return input.getMount().isSupportFragment(path);
-            }
-        }).isPresent()) {
+        if (nonDefaultStores.stream()
+                .map(MountedNodeStore::getMount)
+                .anyMatch(m -> m.isSupportFragment(path))) {
             return true;
         }
         return !mip.getMountsPlacedUnder(path).isEmpty();
@@ -156,12 +132,9 @@ class CompositionContext {
         if (!mount.isSupportFragment(parentPath)) {
             return false;
         }
-        return tryFind(childrenProvider.apply(mns), new Predicate<String>() {
-            @Override
-            public boolean apply(String input) {
-                return input.contains(mount.getPathFragmentName());
-            }
-        }).isPresent();
+
+        return StreamSupport.stream(childrenProvider.apply(mns).spliterator(), 
false)
+                .anyMatch(i -> i.contains(mount.getPathFragmentName()));
     }
 
     Set<MountedNodeStore> getAllMountedNodeStores() {
@@ -172,17 +145,8 @@ class CompositionContext {
         return globalStore.getNodeStore().createBlob(inputStream);
     }
 
-    int getStoresCount() {
-        return nonDefaultStores.size() + 1;
-    }
-
-    Predicate<String> belongsToStore(final MountedNodeStore mountedNodeStore, 
final String parentPath) {
-        return new Predicate<String>() {
-            @Override
-            public boolean apply(String childName) {
-                return getOwningStore(PathUtils.concat(parentPath, childName)) 
== mountedNodeStore;
-            }
-        };
+    boolean belongsToStore(final MountedNodeStore mountedNodeStore, final 
String parentPath, final String childName) {
+        return getOwningStore(PathUtils.concat(parentPath, childName)) == 
mountedNodeStore;
     }
 
     CompositeNodeState createRootNodeState(Map<MountedNodeStore, NodeState> 
rootStates) {

Added: 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/util/Memoizer.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/util/Memoizer.java?rev=1803029&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/util/Memoizer.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/util/Memoizer.java
 Wed Jul 26 09:19:26 2017
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.composite.util;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+
+public final class Memoizer {
+
+    private Memoizer() {
+
+    }
+
+    public static <I, O> Function<I, O> memoize(Function<I, O> f) {
+        ConcurrentMap<I, O> lookup = new ConcurrentHashMap<>();
+        return input -> lookup.computeIfAbsent(input, f);
+    }
+
+}


Reply via email to