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);
+ }
+
+}