You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ca...@apache.org on 2017/10/01 00:42:18 UTC
svn commit: r1810243 - in
/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene:
LuceneIndexProviderServiceTest.java directory/BufferedOakDirectoryTest.java
directory/OakStreamingIndexFileTest.java
Author: catholicon
Date: Sun Oct 1 00:42:18 2017
New Revision: 1810243
URL: http://svn.apache.org/viewvc?rev=1810243&view=rev
Log:
OAK-6269: Support non chunk storage in OakDirectory
Add test for OakStreamingIndexFile and a few tests in BufferedOakDirectoryTest
Added:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakStreamingIndexFileTest.java (with props)
Modified:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexProviderServiceTest.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/BufferedOakDirectoryTest.java
Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexProviderServiceTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexProviderServiceTest.java?rev=1810243&r1=1810242&r2=1810243&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexProviderServiceTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexProviderServiceTest.java Sun Oct 1 00:42:18 2017
@@ -47,6 +47,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.index.IndexPathService;
import org.apache.jackrabbit.oak.plugins.index.fulltext.PreExtractedTextProvider;
import org.apache.jackrabbit.oak.plugins.index.importer.IndexImporterProvider;
+import org.apache.jackrabbit.oak.plugins.index.lucene.directory.BufferedOakDirectory;
import org.apache.jackrabbit.oak.plugins.index.lucene.score.ScorerProviderFactory;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore;
@@ -63,7 +64,6 @@ import org.apache.sling.testing.mock.osg
import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
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;
@@ -316,6 +316,23 @@ public class LuceneIndexProviderServiceT
}
+ @Test
+ public void singleBlobPerIndexFileConfig() throws Exception {
+ Map<String, Object> config = getDefaultConfig();
+ config.put("enableSingleBlobIndexFiles", "true");
+ MockOsgi.activate(service, context.bundleContext(), config);
+ assertTrue("Enabling property must reflect in BufferedOakDirectory state",
+ BufferedOakDirectory.isEnableWritingSingleBlobIndexFile());
+ MockOsgi.deactivate(service, context.bundleContext());
+
+ config = getDefaultConfig();
+ config.put("enableSingleBlobIndexFiles", "false");
+ MockOsgi.activate(service, context.bundleContext(), config);
+ assertFalse("Enabling property must reflect in BufferedOakDirectory state",
+ BufferedOakDirectory.isEnableWritingSingleBlobIndexFile());
+ MockOsgi.deactivate(service, context.bundleContext());
+
+ }
private void reactivate() {
MockOsgi.deactivate(service, context.bundleContext());
Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/BufferedOakDirectoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/BufferedOakDirectoryTest.java?rev=1810243&r1=1810242&r2=1810243&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/BufferedOakDirectoryTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/BufferedOakDirectoryTest.java Sun Oct 1 00:42:18 2017
@@ -22,9 +22,12 @@ import java.util.Arrays;
import java.util.Random;
import java.util.Set;
+import ch.qos.logback.classic.Level;
import com.google.common.collect.Sets;
import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.commons.junit.LogCustomizer;
import org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition;
import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
@@ -37,6 +40,8 @@ import org.junit.Test;
import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.INDEX_DATA_CHILD_NAME;
import static org.apache.jackrabbit.oak.plugins.index.lucene.directory.BufferedOakDirectory.DELETE_THRESHOLD_UNTIL_REOPEN;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.directory.BufferedOakDirectory.ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.directory.BufferedOakDirectory.reReadCommandLineParam;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -143,6 +148,251 @@ public class BufferedOakDirectoryTest {
dir.close();
}
+ @Test
+ public void respectSettingConfigForSingleBlobWrite() {
+ boolean oldVal = BufferedOakDirectory.isEnableWritingSingleBlobIndexFile();
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(true);
+ assertTrue("Flag not setting as set by configuration",
+ BufferedOakDirectory.isEnableWritingSingleBlobIndexFile());
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(false);
+ assertFalse("Flag not setting as set by configuration",
+ BufferedOakDirectory.isEnableWritingSingleBlobIndexFile());
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(oldVal);
+ }
+
+ @Test
+ public void selectWriteStrategyBasedOnFlagAndMode() throws Exception {
+ boolean oldVal = BufferedOakDirectory.isEnableWritingSingleBlobIndexFile();
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(false);
+ try (Directory multiBlobDir = createDir(builder, true)) {
+ IndexOutput multiBlobIndexOutput = multiBlobDir.createOutput("foo", IOContext.DEFAULT);
+
+ multiBlobIndexOutput.writeBytes(randomBytes(100), 0, 100);
+ multiBlobIndexOutput.flush();
+ }
+
+ PropertyState jcrData = builder.getChildNode(":data").getChildNode("foo").getProperty("jcr:data");
+ assertTrue("multiple blobs not written", jcrData.isArray());
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(true);
+ try (Directory multiBlobDir = createDir(builder, true)) {
+ IndexOutput multiBlobIndexOutput = multiBlobDir.createOutput("foo", IOContext.DEFAULT);
+
+ multiBlobIndexOutput.writeBytes(randomBytes(100), 0, 100);
+ multiBlobIndexOutput.flush();
+ }
+
+ jcrData = builder.getChildNode(":data").getChildNode("foo").getProperty("jcr:data");
+ assertFalse("multiple blobs written", jcrData.isArray());
+
+ try (Directory multiBlobDir = createDir(builder, false)) {
+ IndexOutput multiBlobIndexOutput = multiBlobDir.createOutput("foo", IOContext.DEFAULT);
+
+ multiBlobIndexOutput.writeBytes(randomBytes(100), 0, 100);
+ multiBlobIndexOutput.flush();
+ }
+
+ jcrData = builder.getChildNode(":data").getChildNode("foo").getProperty("jcr:data");
+ assertTrue("multiple blobs not written despite disabled buffered directory", jcrData.isArray());
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(oldVal);
+ }
+
+ @Test
+ public void readNonStreamingWhenMultipleBlobsExist() throws Exception {
+ boolean oldVal = BufferedOakDirectory.isEnableWritingSingleBlobIndexFile();
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(false);
+ try (Directory multiBlobDir = createDir(builder, true)) {
+ IndexOutput multiBlobIndexOutput = multiBlobDir.createOutput("foo", IOContext.DEFAULT);
+
+ multiBlobIndexOutput.writeBytes(randomBytes(100), 0, 100);
+ multiBlobIndexOutput.flush();
+ }
+
+ // Enable feature... reader shouldn't care about the flag.
+ // Repo state needs to be used for that
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(true);
+ try (Directory multiBlobDir = createDir(builder, true)) {
+ OakIndexInput multiBlobIndexInput = (OakIndexInput)multiBlobDir.openInput("foo", IOContext.DEFAULT);
+
+ assertTrue("OakBufferedIndexFile must be used",
+ multiBlobIndexInput.file instanceof OakBufferedIndexFile);
+ }
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(oldVal);
+ }
+
+ @Test
+ public void readStreamingWithSingleBlob() throws Exception {
+ boolean oldVal = BufferedOakDirectory.isEnableWritingSingleBlobIndexFile();
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(true);
+ try (Directory multiBlobDir = createDir(builder, true)) {
+ IndexOutput multiBlobIndexOutput = multiBlobDir.createOutput("foo", IOContext.DEFAULT);
+
+ multiBlobIndexOutput.writeBytes(randomBytes(100), 0, 100);
+ multiBlobIndexOutput.flush();
+ }
+
+ // Enable feature... reader shouldn't care about the flag.
+ // Repo state needs to be used for that
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(false);
+ try (Directory multiBlobDir = createDir(builder, true)) {
+ OakIndexInput multiBlobIndexInput = (OakIndexInput)multiBlobDir.openInput("foo", IOContext.DEFAULT);
+
+ assertTrue("OakStreamingIndexFile must be used",
+ multiBlobIndexInput.file instanceof OakStreamingIndexFile);
+ }
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(oldVal);
+ }
+
+ @Test
+ public void writeNonStreamingIfDisabledByFlag() throws Exception {
+ boolean oldVal = BufferedOakDirectory.isEnableWritingSingleBlobIndexFile();
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(false);
+ try (Directory multiBlobDir = createDir(builder, true)) {
+ OakIndexOutput multiBlobIndexOutput = (OakIndexOutput)multiBlobDir.createOutput("foo1", IOContext.DEFAULT);
+
+ assertTrue("OakBufferedIndexFile must be used",
+ multiBlobIndexOutput.file instanceof OakBufferedIndexFile);
+ }
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(true);
+ try (Directory multiBlobDir = createDir(builder, true)) {
+ OakIndexOutput multiBlobIndexOutput = (OakIndexOutput)multiBlobDir.createOutput("foo2", IOContext.DEFAULT);
+
+ assertTrue("OakStreamingIndexFile must be used",
+ multiBlobIndexOutput.file instanceof OakStreamingIndexFile);
+ }
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(oldVal);
+ }
+
+ @Test
+ public void defaultValue() {
+ BufferedOakDirectory bufferedOakDirectory = (BufferedOakDirectory)createDir(builder, true);
+ assertTrue("Flag not setting as set by command line flag",
+ bufferedOakDirectory.isEnableWritingSingleBlobIndexFile());
+ }
+
+ @Test
+ public void commandLineParamSetsValue() {
+ String oldVal = System.getProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM);
+
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, "true");
+ reReadCommandLineParam();
+ assertTrue("Flag not setting as set by command line flag",
+ BufferedOakDirectory.isEnableWritingSingleBlobIndexFile());
+
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, "false");
+ reReadCommandLineParam();
+ assertFalse("Flag not setting as set by command line flag",
+ BufferedOakDirectory.isEnableWritingSingleBlobIndexFile());
+
+ if (oldVal == null) {
+ System.clearProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM);
+ } else {
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, oldVal);
+ }
+ }
+
+ @Test
+ public void commandLineOverridesSetter() {
+ String oldVal = System.getProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM);
+
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, "true");
+ reReadCommandLineParam();
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(false);
+ assertTrue("Flag not setting as set by command line flag",
+ BufferedOakDirectory.isEnableWritingSingleBlobIndexFile());
+
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, "false");
+ reReadCommandLineParam();
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(false);
+ assertFalse("Flag not setting as set by command line flag",
+ BufferedOakDirectory.isEnableWritingSingleBlobIndexFile());
+
+ if (oldVal == null) {
+ System.clearProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM);
+ } else {
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, oldVal);
+ }
+ }
+
+ @Test
+ public void settingConfigDifferentFromCLIWarns() {
+ String oldVal = System.getProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM);
+
+ final LogCustomizer custom = LogCustomizer
+ .forLogger(BufferedOakDirectory.class.getName())
+ .contains("Ignoring configuration ")
+ .enable(Level.WARN).create();
+
+ custom.starting();
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, "true");
+ reReadCommandLineParam();
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(false);
+ assertEquals("Warn on conflicting config on CLI and set method", 1, custom.getLogs().size());
+ custom.finished();
+
+ custom.starting();
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, "false");
+ reReadCommandLineParam();
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(true);
+ assertEquals("Warn on conflicting config on CLI and set method", 1, custom.getLogs().size());
+ custom.finished();
+
+ if (oldVal == null) {
+ System.clearProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM);
+ } else {
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, oldVal);
+ }
+ }
+
+ @Test
+ public void dontWarnUnnecesarily() {
+ String oldVal = System.getProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM);
+
+ final LogCustomizer custom = LogCustomizer
+ .forLogger(BufferedOakDirectory.class.getName())
+ .contains("Ignoring configuration ")
+ .enable(Level.WARN).create();
+
+ custom.starting();
+
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(true);
+ assertEquals("Don't warn unnecessarily", 0, custom.getLogs().size());
+
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, "true");
+ reReadCommandLineParam();
+ assertEquals("Don't warn unnecessarily", 0, custom.getLogs().size());
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(true);
+ assertEquals("Don't warn unnecessarily", 0, custom.getLogs().size());
+ System.clearProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM);
+
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, "false");
+ reReadCommandLineParam();
+ assertEquals("Don't warn unnecessarily", 0, custom.getLogs().size());
+ BufferedOakDirectory.setEnableWritingSingleBlobIndexFile(false);
+ assertEquals("Don't warn unnecessarily", 0, custom.getLogs().size());
+ System.clearProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM);
+
+ custom.finished();
+
+ if (oldVal == null) {
+ System.clearProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM);
+ } else {
+ System.setProperty(ENABLE_WRITING_SINGLE_BLOB_INDEX_FILE_PARAM, oldVal);
+ }
+ }
+
private void assertFile(Directory dir, String file, byte[] expected)
throws IOException {
assertTrue(dir.fileExists(file));
Added: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakStreamingIndexFileTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakStreamingIndexFileTest.java?rev=1810243&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakStreamingIndexFileTest.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakStreamingIndexFileTest.java Sun Oct 1 00:42:18 2017
@@ -0,0 +1,321 @@
+/*
+ * 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.plugins.index.lucene.directory;
+
+import ch.qos.logback.classic.Level;
+import com.google.common.collect.Lists;
+import org.apache.jackrabbit.oak.commons.junit.LogCustomizer;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.lucene.store.ByteArrayDataInput;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Random;
+
+import static org.apache.jackrabbit.oak.plugins.index.lucene.directory.OakStreamingIndexFileTest.BlobFactoryMode.BATCH_READ;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.directory.OakStreamingIndexFileTest.BlobFactoryMode.BYTE_WISE_READ;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.directory.OakStreamingIndexFileTest.FileCreateMode.COPY_BYTES;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.directory.OakStreamingIndexFileTest.FileCreateMode.WRITE_FILE;
+import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@RunWith(Parameterized.class)
+public class OakStreamingIndexFileTest {
+
+ private Random rnd = new Random();
+
+ private NodeState root = EMPTY_NODE;
+
+ private NodeBuilder builder = root.builder();
+
+ private int fileSize = 1000 + rnd.nextInt(1000);
+
+ private final FileCreateMode fileCreateMode;
+ private final BlobFactoryMode blobFactoryMode;
+ private final ModeDependantBlobFactory modeDependantBlobFactory;
+
+ enum BlobFactoryMode {
+ BATCH_READ,
+ BYTE_WISE_READ
+ }
+
+ enum FileCreateMode {
+ WRITE_FILE,
+ COPY_BYTES
+ }
+
+ @Parameterized.Parameters(name="{0}, {1}")
+ public static Collection<Object[]> fixtures() throws Exception {
+ List<Object[]> modes = Lists.newArrayList();
+ modes.add(new Object[]{COPY_BYTES, BYTE_WISE_READ});
+ modes.add(new Object[]{COPY_BYTES, BATCH_READ});
+ modes.add(new Object[]{WRITE_FILE, BYTE_WISE_READ});
+ modes.add(new Object[]{WRITE_FILE, BATCH_READ});
+ return modes;
+ }
+
+ public OakStreamingIndexFileTest(FileCreateMode fileCreateMode, BlobFactoryMode blobFactoryMode) {
+ this.fileCreateMode = fileCreateMode;
+ this.blobFactoryMode = blobFactoryMode;
+ this.modeDependantBlobFactory = new ModeDependantBlobFactory(blobFactoryMode);
+ }
+
+ @Test
+ public void readSanity() throws Exception {
+ byte[] fileBytes = writeFile();
+
+ NodeBuilder fooBuilder = builder.child("foo");
+ try (OakStreamingIndexFile readFile = new OakStreamingIndexFile("foo", fooBuilder, "dirDetails",
+ modeDependantBlobFactory.getNodeBuilderBlobFactory(fooBuilder))
+ ) {
+ byte[] readBytes = new byte[fileBytes.length];
+ readFile.readBytes(readBytes, 0, fileBytes.length);
+
+ assertEquals("Must read same amount of data", fileBytes.length, readBytes.length);
+ assertTrue("Must get back same data", Arrays.equals(readBytes, fileBytes));
+
+ try {
+ readFile.readBytes(readBytes, 0, 1);
+ fail("Must not be able to read past stored number of bytes");
+ } catch (Exception ignored) {
+ // ignore
+ }
+ }
+ }
+
+ @Test
+ public void rangeReadWorks() throws Exception {
+ int numFewBytes = 100;
+
+ byte[] fileBytes = writeFile();
+ byte[] aFewBytes = Arrays.copyOfRange(fileBytes, 1, numFewBytes + 1);
+
+ NodeBuilder fooBuilder = builder.child("foo");
+ try (OakStreamingIndexFile readFile = new OakStreamingIndexFile("foo", fooBuilder, "dirDetails",
+ modeDependantBlobFactory.getNodeBuilderBlobFactory(fooBuilder))
+ ) {
+ readFile.seek(1);
+ assertEquals("Seeking should move position", 1, readFile.position());
+
+ byte[] readBytes = new byte[numFewBytes];
+ readFile.readBytes(readBytes, 0, numFewBytes);
+ assertTrue("Reading a few bytes should be accurate", Arrays.equals(readBytes, aFewBytes));
+ }
+ }
+
+ @Test
+ public void rangeReadWorksOnSeekingBack() throws Exception {
+ int numFewBytes = 100;
+
+ byte[] fileBytes = writeFile();
+ byte[] aFewBytes = Arrays.copyOfRange(fileBytes, 1, numFewBytes + 1);
+
+ NodeBuilder fooBuilder = builder.child("foo");
+ try (OakStreamingIndexFile readFile = new OakStreamingIndexFile("foo", fooBuilder, "dirDetails",
+ modeDependantBlobFactory.getNodeBuilderBlobFactory(fooBuilder))
+ ) {
+ byte[] readBytes = new byte[numFewBytes];
+
+ readFile.seek(100);
+ readFile.readBytes(readBytes, 0, 1);
+ readFile.seek(1);
+ assertEquals("Seeking should move position", 1, readFile.position());
+
+ readFile.readBytes(readBytes, 0, numFewBytes);
+ assertTrue("Reading a few bytes should be accurate", Arrays.equals(readBytes, aFewBytes));
+ }
+ }
+
+ @Test
+ public void cloneCreatesSimilarUnrelatedStreams() throws Exception {
+ int numFewBytes = 100;
+
+ byte[] fileBytes = writeFile();
+ byte[] aFewBytes = Arrays.copyOfRange(fileBytes, 2, numFewBytes + 2);
+
+ byte[] readBytes = new byte[numFewBytes];
+
+ OakStreamingIndexFile readFileClone;
+
+ NodeBuilder fooBuilder = builder.child("foo");
+ try (OakStreamingIndexFile readFile = new OakStreamingIndexFile("foo", fooBuilder, "dirDetails",
+ modeDependantBlobFactory.getNodeBuilderBlobFactory(fooBuilder))
+ ) {
+ readFile.seek(1);
+ readFile.readBytes(readBytes, 0, 1);
+
+ readFileClone = (OakStreamingIndexFile) readFile.clone();
+
+ readFile.readBytes(readBytes, 0, numFewBytes);
+ }
+
+ assertNotNull("Clone reader should have been created", readFileClone);
+
+ try {
+ readFileClone.readBytes(readBytes, 0, numFewBytes);
+ assertTrue("Clone reader should start from same position as source",
+ Arrays.equals(readBytes, aFewBytes));
+ } finally {
+ readFileClone.close();
+ }
+ }
+
+ @Test
+ public void streamingWritesDontWorkPiecewise() throws Exception {
+ Assume.assumeTrue("Piece write makes sense for " + WRITE_FILE + " mode", fileCreateMode == WRITE_FILE);
+ NodeBuilder fooBuilder = builder.child("foo");
+ try (OakStreamingIndexFile writeFile = new OakStreamingIndexFile("foo", fooBuilder, "dirDetails",
+ modeDependantBlobFactory.getNodeBuilderBlobFactory(fooBuilder))
+ ) {
+ byte[] fileBytes = randomBytes(fileSize);
+
+ writeFile.writeBytes(fileBytes, 0, fileBytes.length);
+ try {
+ writeFile.writeBytes(fileBytes, 0, 1);
+ fail("Multiple write bytes must not be allowed with streaming writes");
+ } catch (Exception ignored) {
+ //ignore
+ }
+ writeFile.flush();
+ }
+ }
+
+ @Test
+ public void seekScenarios() throws Exception {
+ byte[] fileBytes = writeFile();
+
+ NodeBuilder fooBuilder = builder.child("foo");
+ try (OakStreamingIndexFile readFile = new OakStreamingIndexFile("foo", fooBuilder, "dirDetails",
+ modeDependantBlobFactory.getNodeBuilderBlobFactory(fooBuilder))
+ ) {
+ byte[] aFewBytes = new byte[10];
+ byte[] expectedFewBytes;
+
+ expectedFewBytes = Arrays.copyOfRange(fileBytes, 10, 10 + aFewBytes.length);
+ readFile.seek(10);
+ readFile.readBytes(aFewBytes, 0, aFewBytes.length);
+ assertTrue("Range read after seek should read accurately",
+ Arrays.equals(expectedFewBytes, aFewBytes));
+
+
+ expectedFewBytes = Arrays.copyOfRange(fileBytes, 25, 25 + aFewBytes.length);
+ readFile.seek(25);
+ readFile.readBytes(aFewBytes, 0, aFewBytes.length);
+ assertTrue("Range read after seek should read accurately",
+ Arrays.equals(expectedFewBytes, aFewBytes));
+
+
+ expectedFewBytes = Arrays.copyOfRange(fileBytes, 2, 2 + aFewBytes.length);
+ readFile.seek(2);
+ readFile.readBytes(aFewBytes, 0, aFewBytes.length);
+ assertTrue("Range read after backward seek should read accurately",
+ Arrays.equals(expectedFewBytes, aFewBytes));
+
+ }
+ }
+
+ @Test
+ public void logWarnWhenSeekingBackAfterRead() throws Exception {
+ byte[] fileBytes = writeFile();
+
+ LogCustomizer logRecorder = LogCustomizer
+ .forLogger(OakStreamingIndexFile.class.getName()).enable(Level.WARN)
+ .contains("Seeking back on streaming index file").create();
+
+ NodeBuilder fooBuilder = builder.child("foo");
+ try (OakStreamingIndexFile readFile = new OakStreamingIndexFile("foo", fooBuilder, "dirDetails",
+ modeDependantBlobFactory.getNodeBuilderBlobFactory(fooBuilder))
+ ) {
+ logRecorder.starting();
+ byte[] readBytes = new byte[fileBytes.length];
+
+ readFile.readBytes(readBytes, 0, 10);
+ assertEquals("Don't log for simple reads", 0, logRecorder.getLogs().size());
+
+ readFile.seek(12);
+ assertEquals("Don't log for forward seeks", 0, logRecorder.getLogs().size());
+
+ readFile.seek(2);
+ assertEquals("Log warning for backward seeks", 1, logRecorder.getLogs().size());
+ }
+
+ logRecorder.finished();
+ }
+
+ static class ModeDependantBlobFactory {
+
+ private final BlobFactoryMode blobFactoryMode;
+
+ ModeDependantBlobFactory(BlobFactoryMode blobFactoryMode) {
+ this.blobFactoryMode = blobFactoryMode;
+ }
+
+ BlobFactory getNodeBuilderBlobFactory(final NodeBuilder builder) {
+ final BlobFactory delegate = BlobFactory.getNodeBuilderBlobFactory(builder);
+ return in -> {
+ if (blobFactoryMode == BYTE_WISE_READ) {
+ return delegate.createBlob(new InputStream() {
+ @Override
+ public int read() throws IOException {
+ return in.read();
+ }
+ });
+ } else {
+ return delegate.createBlob(in);
+ }
+ };
+ }
+ }
+
+ private byte[] writeFile() throws Exception {
+ byte[] fileBytes = randomBytes(fileSize);
+
+ NodeBuilder fooBuilder = builder.child("foo");
+ try (OakStreamingIndexFile writeFile = new OakStreamingIndexFile("foo", fooBuilder, "dirDetails",
+ modeDependantBlobFactory.getNodeBuilderBlobFactory(fooBuilder))
+ ) {
+ if (fileCreateMode == COPY_BYTES) {
+ writeFile.copyBytes(new ByteArrayDataInput(fileBytes), fileBytes.length);
+ } else {
+ writeFile.writeBytes(fileBytes, 0, fileBytes.length);
+ }
+ writeFile.flush();
+ }
+
+ return fileBytes;
+ }
+
+ private byte[] randomBytes(int size) {
+ byte[] data = new byte[size];
+ rnd.nextBytes(data);
+ return data;
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakStreamingIndexFileTest.java
------------------------------------------------------------------------------
svn:eol-style = native