Index: oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/AbstractFileStore.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/AbstractFileStore.java (date 1477403102000) +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/AbstractFileStore.java (revision ) @@ -265,6 +265,7 @@ return tracker; } + @Nonnull public abstract SegmentWriter getWriter(); @Nonnull Index: oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriterBuilder.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriterBuilder.java (date 1477403102000) +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriterBuilder.java (revision ) @@ -21,12 +21,15 @@ import static com.google.common.base.Preconditions.checkNotNull; +import java.io.IOException; + import javax.annotation.Nonnull; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import org.apache.jackrabbit.oak.segment.WriterCacheManager.Empty; import org.apache.jackrabbit.oak.segment.file.FileStore; +import org.apache.jackrabbit.oak.segment.file.ReadOnlyFileStore; import org.apache.jackrabbit.oak.segment.http.HttpStore; import org.apache.jackrabbit.oak.segment.memory.MemoryStore; @@ -152,6 +155,32 @@ ); } + /** + * Build a {@code SegmentWriter} for a {@code ReadOnlyFileStore}. + * Attempting to write to the returned writer will cause a + * {@code UnsupportedOperationException} to be thrown. + */ + @Nonnull + public SegmentWriter build(@Nonnull ReadOnlyFileStore store) { + return new SegmentWriter( + checkNotNull(store), + store.getReader(), + store.getBlobStore(), + cacheManager, + new WriteOperationHandler() { + @Nonnull + @Override + public RecordId execute(@Nonnull WriteOperation writeOperation) throws IOException { + throw new UnsupportedOperationException("Cannot write to read-only store"); + } + + @Override + public void flush() throws IOException { + throw new UnsupportedOperationException("Cannot write to read-only store"); + } + }); + } + /** * Build a {@code SegmentWriter} for a {@code MemoryStore}. */ Index: oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/ReadOnlyFileStore.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/ReadOnlyFileStore.java (date 1477403102000) +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/ReadOnlyFileStore.java (revision ) @@ -24,6 +24,7 @@ import static com.google.common.collect.Maps.newHashMap; import static com.google.common.collect.Sets.newHashSet; import static java.util.Collections.emptyMap; +import static org.apache.jackrabbit.oak.segment.SegmentWriterBuilder.segmentWriterBuilder; import java.io.File; import java.io.IOException; @@ -61,6 +62,9 @@ private final List readers; + @Nonnull + private final SegmentWriter writer; + private ReadOnlyRevisions revisions; private RecordId currentHead; @@ -84,6 +88,8 @@ boolean recover = i == indices.length - 1; readers.add(TarReader.openRO(map.get(indices[i]), memoryMapping, recover, recovery)); } + + writer = segmentWriterBuilder("read-only").withoutCache().build(this); log.info("TarMK ReadOnly opened: {} (mmap={})", directory, memoryMapping); } @@ -209,9 +215,10 @@ log.info("TarMK closed: {}", directory); } + @Nonnull @Override public SegmentWriter getWriter() { - return null; + return writer; } public Map> getTarReaderIndex() { Index: oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/ReadOnlyStoreTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/ReadOnlyStoreTest.java (date 1477403102000) +++ oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/ReadOnlyStoreTest.java (revision ) @@ -19,16 +19,21 @@ package org.apache.jackrabbit.oak.segment; import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder; +import static org.junit.Assert.assertEquals; import java.io.File; import java.io.IOException; +import org.apache.jackrabbit.oak.api.CommitFailedException; import org.apache.jackrabbit.oak.segment.file.FileStore; import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException; import org.apache.jackrabbit.oak.segment.file.ReadOnlyFileStore; +import org.apache.jackrabbit.oak.spi.commit.CommitInfo; +import org.apache.jackrabbit.oak.spi.commit.EmptyHook; +import org.apache.jackrabbit.oak.spi.state.NodeBuilder; +import org.apache.jackrabbit.oak.spi.state.NodeState; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -38,12 +43,14 @@ public TemporaryFolder folder = new TemporaryFolder(new File("target")); private ReadOnlyFileStore fileStore; + private SegmentNodeStore store; @Before public void setup() throws IOException, InvalidFileStoreVersionException { File path = folder.getRoot(); initStoreAt(path); fileStore = fileStoreBuilder(path).buildReadOnly(); + store = SegmentNodeStoreBuilders.builder(fileStore).build(); } private static void initStoreAt(File path) throws InvalidFileStoreVersionException, IOException { @@ -57,8 +64,16 @@ } @Test - @Ignore("OAK-5002") // FIXME OAK-5002 - public void createStore() { - SegmentNodeStoreBuilders.builder(fileStore).build(); + public void getRoot() { + NodeState root = store.getRoot(); + assertEquals(0, root.getChildNodeCount(1)); } + + @Test(expected = UnsupportedOperationException.class) + public void setRoot() throws CommitFailedException { + NodeBuilder root = store.getRoot().builder(); + root.setChildNode("foo"); + store.merge(root, EmptyHook.INSTANCE, CommitInfo.EMPTY); + } + }