Author: tomekr
Date: Mon Sep 11 13:49:04 2017
New Revision: 1808026

URL: http://svn.apache.org/viewvc?rev=1808026&view=rev
Log:
OAK-6644: Use ReadOnlyNodeBuilder for the read-only mounts

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/NodeMap.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=1808026&r1=1808025&r2=1808026&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
 Mon Sep 11 13:49:04 2017
@@ -724,23 +724,10 @@ public class CompositeNodeStoreTest {
         
//assertTrue(builderFromState.getBaseState().getBoolean("newProperty")); // 
FIXME
     }
 
-    @Test
+    @Test (expected = UnsupportedOperationException.class)
     public void readOnlyMountRejectsChanges() throws Exception {
-        NodeState oldState = store.getRoot();
-        try {
-            NodeBuilder builder = store.getRoot().builder();
-            builder.getChildNode("readOnly").child("newChild");
-            builder.getChildNode("libs").child("otherChild");
-            store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
-        } catch (CommitFailedException e) {
-            // expected
-            // validate that changes were not applied
-            CountingDiff countingDiff = new CountingDiff();
-            store.getRoot().compareAgainstBaseState(oldState, countingDiff);
-            assertThat("Unexpected number of changes", 
countingDiff.getNumChanges(), equalTo(0));
-        } catch ( Exception e ) {
-            throw e;
-        }
+        NodeBuilder builder = store.getRoot().builder();
+        builder.getChildNode("readOnly").child("newChild");
     }
 
     @Test

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=1808026&r1=1808025&r2=1808026&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
 Mon Sep 11 13:49:04 2017
@@ -50,8 +50,14 @@ 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(builder.getNodeBuilder(mns)));
-            beforeStates.put(mns, builder.getNodeBuilder(mns).getBaseState());
+            if (mns.getMount().isReadOnly()) {
+                NodeState root = mns.getNodeStore().getRoot();
+                afterStates.put(mns, root);
+                beforeStates.put(mns, root);
+            } else {
+                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=1808026&r1=1808025&r2=1808026&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
 Mon Sep 11 13:49:04 2017
@@ -42,14 +42,11 @@ class CompositeNodeBuilder implements No
 
     private final CompositionContext ctx;
 
-    private NodeMap<NodeBuilder> nodeBuilders;
+    private final NodeMap<NodeBuilder> nodeBuilders;
 
-    private final MountedNodeStore owningStore;
-
-    CompositeNodeBuilder(String path, NodeMap<NodeBuilder> nodeBuilders, 
CompositionContext ctx) {
+    CompositeNodeBuilder(NodeMap<NodeBuilder> nodeBuilders, CompositionContext 
ctx) {
         this.ctx = ctx;
         this.nodeBuilders = nodeBuilders;
-        this.owningStore = ctx.getOwningStore(path);
     }
 
     NodeBuilder getNodeBuilder(MountedNodeStore mns) {
@@ -58,12 +55,12 @@ class CompositeNodeBuilder implements No
 
     @Override
     public CompositeNodeState getNodeState() {
-        return new CompositeNodeState(getPath(), nodeBuilders.getAndApply(n -> 
n.exists() ? n.getNodeState() : MISSING_NODE), ctx);
+        return new CompositeNodeState(getPath(), 
nodeBuilders.getAndApply((mns, b) -> b.exists() ? b.getNodeState() : 
MISSING_NODE), ctx);
     }
 
     @Override
     public CompositeNodeState getBaseState() {
-        return new CompositeNodeState(getPath(), 
nodeBuilders.getAndApply(NodeBuilder::getBaseState), ctx);
+        return new CompositeNodeState(getPath(), 
nodeBuilders.getAndApply((mns, b) -> b.getBaseState()), ctx);
     }
 
     // node or property-related methods ; directly delegate to wrapped builder
@@ -213,7 +210,7 @@ class CompositeNodeBuilder implements No
         if (!ctx.shouldBeComposite(childPath)) {
             return 
nodeBuilders.get(ctx.getOwningStore(childPath)).getChildNode(name);
         }
-        return new CompositeNodeBuilder(childPath, nodeBuilders.lazyApply(b -> 
b.getChildNode(name)), ctx);
+        return new CompositeNodeBuilder(nodeBuilders.lazyApply((mns, b) -> 
b.getChildNode(name)), ctx);
     }
 
     @Override
@@ -226,14 +223,14 @@ class CompositeNodeBuilder implements No
         checkState(exists(), "This builder does not exist: " + 
PathUtils.getName(getPath()));
         String childPath = simpleConcat(getPath(), name);
         final MountedNodeStore childStore = ctx.getOwningStore(childPath);
-        if (childStore != owningStore && 
!nodeBuilders.get(childStore).exists()) {
+        if (childStore != ctx.getGlobalStore() && 
!nodeBuilders.get(childStore).exists()) {
             throw new IllegalStateException("The mount root doesn't exist: " + 
getPath() + " for " + childStore);
         }
         final NodeBuilder childBuilder = 
nodeBuilders.get(childStore).setChildNode(name, nodeState);
         if (!ctx.shouldBeComposite(childPath)) {
             return childBuilder;
         }
-        return new CompositeNodeBuilder(childPath, nodeBuilders.lazyApply(b -> 
b.getChildNode(name)).replaceNode(childStore, childBuilder), ctx);
+        return new CompositeNodeBuilder(nodeBuilders.lazyApply((mns, b) -> 
b.getChildNode(name)).replaceNode(childStore, childBuilder), ctx);
     }
 
     @Override
@@ -252,7 +249,7 @@ class CompositeNodeBuilder implements No
     }
 
     private NodeBuilder getWrappedNodeBuilder() {
-        return nodeBuilders.get(owningStore);
+        return nodeBuilders.get(ctx.getGlobalStore());
     }
 
     String getPath() {

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=1808026&r1=1808025&r2=1808026&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
 Mon Sep 11 13:49:04 2017
@@ -26,6 +26,7 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.ReadOnlyBuilder;
 
 import java.util.List;
 
@@ -54,15 +55,12 @@ class CompositeNodeState extends Abstrac
 
     private final CompositionContext ctx;
 
-    private final MountedNodeStore owningStore;
-
     private final String path;
 
     CompositeNodeState(String path, NodeMap<NodeState> nodeStates, 
CompositionContext ctx) {
         this.path = ctx.getPathCache().get(path);
         this.ctx = ctx;
         this.nodeStates = nodeStates;
-        this.owningStore = ctx.getOwningStore(getPath());
     }
 
     NodeState getNodeState(MountedNodeStore mns) {
@@ -109,7 +107,7 @@ class CompositeNodeState extends Abstrac
         if (!ctx.shouldBeComposite(childPath)) {
             return 
nodeStates.get(ctx.getOwningStore(childPath)).getChildNode(name);
         }
-        NodeMap<NodeState> newNodeStates = nodeStates.lazyApply(n -> 
n.getChildNode(name));
+        NodeMap<NodeState> newNodeStates = nodeStates.lazyApply((mns, n) -> 
n.getChildNode(name));
         return new CompositeNodeState(childPath, newNodeStates, ctx);
     }
 
@@ -159,9 +157,9 @@ class CompositeNodeState extends Abstrac
         if (base instanceof CompositeNodeState) {
             CompositeNodeState multiBase = (CompositeNodeState) base;
             NodeStateDiff wrappingDiff = new WrappingDiff(diff, multiBase);
-            boolean full = 
getWrappedNodeState().compareAgainstBaseState(multiBase.getWrappedNodeState(), 
new ChildrenDiffFilter(wrappingDiff, owningStore, true));
+            boolean full = 
getWrappedNodeState().compareAgainstBaseState(multiBase.getWrappedNodeState(), 
new ChildrenDiffFilter(wrappingDiff, ctx.getGlobalStore(), true));
             for (MountedNodeStore mns : 
ctx.getContributingStoresForNodes(path, nodeStates)) {
-                if (owningStore == mns) {
+                if (ctx.getGlobalStore() == mns) {
                     continue;
                 }
                 NodeStateDiff childrenDiffFilter = new 
ChildrenDiffFilter(wrappingDiff, mns, false);
@@ -178,11 +176,17 @@ class CompositeNodeState extends Abstrac
     // write operations
     @Override
     public CompositeNodeBuilder builder() {
-        return new CompositeNodeBuilder(getPath(), 
nodeStates.lazyApply(NodeState::builder), ctx);
+        return new CompositeNodeBuilder(nodeStates.lazyApply((mns, n) -> {
+            if (mns.getMount().isReadOnly()) {
+                return new ReadOnlyBuilder(n);
+            } else {
+                return n.builder();
+            }
+        }), ctx);
     }
 
     private NodeState getWrappedNodeState() {
-        return nodeStates.get(owningStore);
+        return nodeStates.get(ctx.getGlobalStore());
     }
 
     private boolean belongsToStore(MountedNodeStore mns, String childName) {

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=1808026&r1=1808025&r2=1808026&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
 Mon Sep 11 13:49:04 2017
@@ -224,9 +224,14 @@ public class CompositeNodeStore implemen
         CompositeNodeBuilder nodeBuilder = (CompositeNodeBuilder) builder;
         Map<MountedNodeStore, NodeState> resultStates = newHashMap();
         for (MountedNodeStore mountedNodeStore : 
ctx.getAllMountedNodeStores()) {
-            NodeStore nodeStore = mountedNodeStore.getNodeStore();
-            NodeBuilder partialBuilder = 
nodeBuilder.getNodeBuilder(mountedNodeStore);
-            NodeState result = nodeStore.reset(partialBuilder);
+            NodeState result;
+            if (mountedNodeStore.getMount().isReadOnly()) {
+                result = mountedNodeStore.getNodeStore().getRoot();
+            } else {
+                NodeStore nodeStore = mountedNodeStore.getNodeStore();
+                NodeBuilder partialBuilder = 
nodeBuilder.getNodeBuilder(mountedNodeStore);
+                result = nodeStore.reset(partialBuilder);
+            }
             resultStates.put(mountedNodeStore, result);
         }
         return ctx.createRootNodeState(resultStates);

Modified: 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/NodeMap.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/NodeMap.java?rev=1808026&r1=1808025&r2=1808026&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/NodeMap.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/NodeMap.java
 Mon Sep 11 13:49:04 2017
@@ -22,6 +22,7 @@ import com.google.common.collect.Immutab
 import org.apache.jackrabbit.oak.spi.mount.Mount;
 
 import java.util.Map;
+import java.util.function.BiFunction;
 import java.util.function.Function;
 import java.util.function.Supplier;
 
@@ -48,18 +49,22 @@ public class NodeMap<T> {
         return suppliers.get(nodeStore).get();
     }
 
-    public <R> NodeMap<R> getAndApply(Function<T, R> function) {
+    public <R> NodeMap<R> getAndApply(BiFunction<MountedNodeStore, T, R> 
function) {
         ImmutableMap.Builder<MountedNodeStore, CacheableSupplier<R>> 
newSuppliers = ImmutableMap.builder();
-        suppliers.forEach((mns, node) -> newSuppliers.put(mns, 
node.getAndApply(function)));
+        suppliers.forEach((mns, node) -> newSuppliers.put(mns, 
node.getAndApply(curry(function, mns))));
         return new NodeMap<>(newSuppliers.build());
     }
 
-    public <R> NodeMap<R> lazyApply(Function<T, R> function) {
+    public <R> NodeMap<R> lazyApply(BiFunction<MountedNodeStore, T, R> 
function) {
         ImmutableMap.Builder<MountedNodeStore, CacheableSupplier<R>> 
newSuppliers = ImmutableMap.builder();
-        suppliers.forEach((mns, node) -> newSuppliers.put(mns, 
node.lazyApply(function)));
+        suppliers.forEach((mns, node) -> newSuppliers.put(mns, 
node.lazyApply(curry(function, mns))));
         return new NodeMap<>(newSuppliers.build());
     }
 
+    private static <T, U, R> Function<U, R> curry(BiFunction<T, U, R> 
function, T value) {
+        return u -> function.apply(value, u);
+    }
+
     public NodeMap<T> replaceNode(MountedNodeStore nodeStore, T node) {
         ImmutableMap.Builder<MountedNodeStore, CacheableSupplier<T>> 
newSuppliers = ImmutableMap.builder();
         suppliers.forEach((mns, n) -> {
@@ -77,7 +82,7 @@ public class NodeMap<T> {
 
         private volatile T value;
 
-        public CacheableSupplier(Supplier<T> supplier) {
+        private CacheableSupplier(Supplier<T> supplier) {
             this.supplier = supplier;
         }
 


Reply via email to