Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java (revision 1845889) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUpdate.java (working copy) @@ -61,6 +61,7 @@ import org.apache.jackrabbit.oak.spi.state.NodeBuilder; import org.apache.jackrabbit.oak.spi.state.NodeState; import org.apache.jackrabbit.oak.spi.state.NodeStateUtils; +import org.apache.jackrabbit.oak.spi.state.ReadOnlyBuilder; import org.apache.jackrabbit.util.ISO8601; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -318,7 +319,12 @@ if (NodeStateUtils.isHidden(rm)) { NodeBuilder childNode = definition.getChildNode(rm); if (!childNode.getBoolean(IndexConstants.REINDEX_RETAIN)) { - definition.getChildNode(rm).remove(); + NodeBuilder child = definition.getChildNode(rm); + if (child instanceof ReadOnlyBuilder) { + log.debug("Preserve read-only child node on reindex: " + rm); + } else { + child.remove(); + } } } } Index: oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakDirectory.java =================================================================== --- oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakDirectory.java (revision 1845889) +++ oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakDirectory.java (working copy) @@ -36,6 +36,7 @@ import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants; import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore; import org.apache.jackrabbit.oak.spi.state.NodeBuilder; +import org.apache.jackrabbit.oak.spi.state.ReadOnlyBuilder; import org.apache.lucene.store.Directory; import org.apache.lucene.store.IOContext; import org.apache.lucene.store.IndexInput; @@ -174,7 +175,11 @@ } else { LOG.debug("Not marking {} under {} for active deletion", name, indexName); } - f.remove(); + if (f instanceof ReadOnlyBuilder) { + LOG.debug("Preserve read-only node: " + name); + } else { + f.remove(); + } markDirty(); } @@ -253,7 +258,11 @@ public void close() throws IOException { if (!readOnly && definition.saveDirListing()) { if (!fileNamesAtStart.equals(fileNames)) { - directoryBuilder.setProperty(createProperty(PROP_DIR_LISTING, fileNames, STRINGS)); + if (directoryBuilder instanceof ReadOnlyBuilder) { + LOG.debug("Preserve files of read-only directory: " + fileNames); + } else { + directoryBuilder.setProperty(createProperty(PROP_DIR_LISTING, fileNames, STRINGS)); + } } } } @@ -296,12 +305,16 @@ NodeBuilder file = directoryBuilder.getChildNode(name); if (file.exists()) { // overwrite potentially already existing child - NodeBuilder destFile = dest.directoryBuilder.setChildNode(name, EMPTY_NODE); - for (PropertyState p : file.getProperties()) { - destFile.setProperty(p); + if (dest.directoryBuilder instanceof ReadOnlyBuilder) { + LOG.debug("Preserve read-only child: " + name); + } else { + NodeBuilder destFile = dest.directoryBuilder.setChildNode(name, EMPTY_NODE); + for (PropertyState p : file.getProperties()) { + destFile.setProperty(p); + } + dest.fileNames.add(name); + dest.markDirty(); } - dest.fileNames.add(name); - dest.markDirty(); } } Index: oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java =================================================================== --- oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java (revision 1847115) +++ oak-store-composite/src/main/java/org/apache/jackrabbit/oak/composite/CompositeNodeBuilder.java (working copy) @@ -25,12 +25,13 @@ import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder; 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.List; -import static com.google.common.base.Preconditions.checkState; import static java.lang.Long.MAX_VALUE; import static java.util.Collections.singleton; import static org.apache.jackrabbit.oak.composite.CompositeNodeState.STOP_COUNTING_CHILDREN; @@ -40,6 +41,8 @@ class CompositeNodeBuilder implements NodeBuilder { + private final static Logger LOG = LoggerFactory.getLogger(CompositeNodeBuilder.class); + private final CompositionContext ctx; private final NodeMap nodeBuilders; @@ -227,9 +230,14 @@ throw new IllegalStateException("This builder does not exist: " + PathUtils.getName(getPath())); } String childPath = simpleConcat(getPath(), name); - final MountedNodeStore childStore = ctx.getOwningStore(childPath); + MountedNodeStore childStore = ctx.getOwningStore(childPath); if (childStore != ctx.getGlobalStore() && !nodeBuilders.get(childStore).exists()) { - throw new IllegalStateException("The mount root doesn't exist: " + getPath() + " for " + childStore); + // if it doesn't exist in the read-only repository, create it in the global repository + // (needed for example for a new index) + if (LOG.isDebugEnabled()) { + LOG.debug("Creating node in the global store; will become invisible once overlayed: " + childPath); + } + childStore = ctx.getGlobalStore(); } final NodeBuilder childBuilder = nodeBuilders.get(childStore).setChildNode(name, nodeState); if (!ctx.shouldBeComposite(childPath)) {