Author: catholicon
Date: Sun Oct 1 00:41:46 2017
New Revision: 1810241
URL: http://svn.apache.org/viewvc?rev=1810241&view=rev
Log:
OAK-6269: Support non chunk storage in OakDirectory
Extract OakIndexFile methods used in OakIndexInput and OakIndexOutput to
an interface
Added:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakBufferedIndexFile.java
- copied, changed from r1810085,
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexFile.java
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexFile.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexInput.java
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexOutput.java
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakDirectoryTest.java
Copied:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakBufferedIndexFile.java
(from r1810085,
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexFile.java)
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakBufferedIndexFile.java?p2=jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakBufferedIndexFile.java&p1=jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexFile.java&r1=1810085&r2=1810241&rev=1810241&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexFile.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakBufferedIndexFile.java
Sun Oct 1 00:41:46 2017
@@ -23,8 +23,6 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.StringUtils;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import java.io.ByteArrayInputStream;
@@ -45,9 +43,7 @@ import static org.apache.jackrabbit.oak.
/**
* A file, which might be split into multiple blobs.
*/
-class OakIndexFile {
- static Logger LOG = LoggerFactory.getLogger(OakIndexFile.class);
-
+class OakBufferedIndexFile implements OakIndexFile {
/**
* Size of the blob entries to which the Lucene files are split.
* Set to higher than the 4kB inline limit for the BlobStore,
@@ -118,8 +114,8 @@ class OakIndexFile {
private final BlobFactory blobFactory;
- public OakIndexFile(String name, NodeBuilder file, String dirDetails,
- @Nonnull BlobFactory blobFactory) {
+ public OakBufferedIndexFile(String name, NodeBuilder file, String
dirDetails,
+ @Nonnull BlobFactory blobFactory) {
this.name = name;
this.file = file;
this.dirDetails = dirDetails;
@@ -145,7 +141,7 @@ class OakIndexFile {
}
}
- private OakIndexFile(OakIndexFile that) {
+ private OakBufferedIndexFile(OakBufferedIndexFile that) {
this.name = that.name;
this.file = that.file;
this.dirDetails = that.dirDetails;
@@ -198,45 +194,33 @@ class OakIndexFile {
}
}
- /**
- * Duplicates this instance to be used by a different consumer/thread.
- * State of the cloned instance is same as original. Once cloned, the
states
- * would change separately according to how are they accessed.
- *
- * @return cloned instance
- */
+ @Override
public OakIndexFile clone() {
- return new OakIndexFile(this);
+ return new OakBufferedIndexFile(this);
}
- /**
- * @return length of index file
- */
+ @Override
public long length() {
return length;
}
- /**
- * @return current location of access
- */
+ @Override
public long position() {
return position;
}
+ @Override
public void close() {
this.blob = null;
this.data = null;
}
+ @Override
public boolean isClosed() {
return blob == null && data == null;
}
- /**
- * Seek current location of access to {@code pos}
- * @param pos
- * @throws IOException
- */
+ @Override
public void seek(long pos) throws IOException {
// seek() may be called with pos == length
// see https://issues.apache.org/jira/browse/LUCENE-1196
@@ -249,14 +233,7 @@ class OakIndexFile {
}
}
- /**
- * Read {@code len} number of bytes from underlying storage and copy them
- * into byte array {@code b} starting at {@code offset}
- * @param b byte array to copy contents read from storage
- * @param offset index into {@code b} where the copy begins
- * @param len numeber of bytes to be read from storage
- * @throws IOException
- */
+ @Override
public void readBytes(byte[] b, int offset, int len)
throws IOException {
checkPositionIndexes(offset, offset + len, checkNotNull(b).length);
@@ -285,14 +262,7 @@ class OakIndexFile {
}
}
- /**
- * Writes {@code len} number of bytes from byte array {@code b}
- * starting at {@code offset} into the underlying storage
- * @param b byte array to copy contents into the storage
- * @param offset index into {@code b} where the copy begins
- * @param len numeber of bytes to be written to storage
- * @throws IOException
- */
+ @Override
public void writeBytes(byte[] b, int offset, int len)
throws IOException {
int i = (int) (position / blobSize);
@@ -343,11 +313,7 @@ class OakIndexFile {
return null;
}
- /**
- * Flushes the content into storage. Before calling this method, written
- * content only exist in memory
- * @throws IOException
- */
+ @Override
public void flush() throws IOException {
flushBlob();
if (dataModified) {
@@ -362,9 +328,7 @@ class OakIndexFile {
return name;
}
- /**
- * @return name of the index being accessed
- */
+ @Override
public String getName() {
return name;
}
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexFile.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexFile.java?rev=1810241&r1=1810240&r2=1810241&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexFile.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexFile.java
Sun Oct 1 00:41:46 2017
@@ -1,202 +1,33 @@
-/*
- * 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 com.google.common.io.ByteStreams;
-import com.google.common.primitives.Ints;
-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.StringUtils;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.annotation.Nonnull;
-import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.SequenceInputStream;
-import java.util.List;
-
-import static com.google.common.base.Preconditions.checkElementIndex;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkPositionIndexes;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Lists.newArrayList;
-import static org.apache.jackrabbit.JcrConstants.JCR_DATA;
-import static org.apache.jackrabbit.JcrConstants.JCR_LASTMODIFIED;
-import static org.apache.jackrabbit.oak.api.Type.BINARIES;
-
-/**
- * A file, which might be split into multiple blobs.
- */
-class OakIndexFile {
- static Logger LOG = LoggerFactory.getLogger(OakIndexFile.class);
-
- /**
- * Size of the blob entries to which the Lucene files are split.
- * Set to higher than the 4kB inline limit for the BlobStore,
- */
- static final int DEFAULT_BLOB_SIZE = 32 * 1024;
-
- /**
- * The file name.
- */
- private final String name;
-
- /**
- * The node that contains the data for this file.
- */
- private final NodeBuilder file;
-
- /**
- * The maximum size of each blob.
- */
- private final int blobSize;
+public interface OakIndexFile {
/**
- * The current position within the file (for positioned read and write
- * operations).
- */
- private long position = 0;
-
- /**
- * The length of the file.
- */
- private long length;
-
- /**
- * The list of blobs (might be empty).
- * The last blob has a size of 1 up to blobSize.
- * All other blobs have a size of blobSize.
+ * @return name of the index being accessed
*/
- private List<Blob> data;
+ String getName();
/**
- * Whether the data was modified since it was last flushed. If yes, on a
- * flush, the metadata, and the list of blobs need to be stored.
+ * @return length of index file
*/
- private boolean dataModified = false;
+ long length();
- /**
- * The index of the currently loaded blob.
- */
- private int index = -1;
+ boolean isClosed();
- /**
- * The data of the currently loaded blob.
- */
- private byte[] blob;
+ void close();
/**
- * The unique key that is used to make the content unique (to allow
removing binaries from the blob store without risking to remove binaries that
are still needed).
+ * @return current location of access
*/
- private final byte[] uniqueKey;
+ long position();
/**
- * Whether the currently loaded blob was modified since the blob was
- * flushed.
+ * Seek current location of access to {@code pos}
+ * @param pos
+ * @throws IOException
*/
- private boolean blobModified = false;
-
- private final String dirDetails;
-
- private final BlobFactory blobFactory;
-
- public OakIndexFile(String name, NodeBuilder file, String dirDetails,
- @Nonnull BlobFactory blobFactory) {
- this.name = name;
- this.file = file;
- this.dirDetails = dirDetails;
- this.blobSize = determineBlobSize(file);
- this.uniqueKey = readUniqueKey(file);
- this.blob = new byte[blobSize];
- this.blobFactory = checkNotNull(blobFactory);
-
- PropertyState property = file.getProperty(JCR_DATA);
- if (property != null && property.getType() == BINARIES) {
- this.data = newArrayList(property.getValue(BINARIES));
- } else {
- this.data = newArrayList();
- }
-
- this.length = (long)data.size() * blobSize;
- if (!data.isEmpty()) {
- Blob last = data.get(data.size() - 1);
- this.length -= blobSize - last.length();
- if (uniqueKey != null) {
- this.length -= uniqueKey.length;
- }
- }
- }
-
- private OakIndexFile(OakIndexFile that) {
- this.name = that.name;
- this.file = that.file;
- this.dirDetails = that.dirDetails;
- this.blobSize = that.blobSize;
- this.uniqueKey = that.uniqueKey;
- this.blob = new byte[blobSize];
-
- this.position = that.position;
- this.length = that.length;
- this.data = newArrayList(that.data);
- this.dataModified = that.dataModified;
- this.blobFactory = that.blobFactory;
- }
-
- private void loadBlob(int i) throws IOException {
- checkElementIndex(i, data.size());
- if (index != i) {
- flushBlob();
- checkState(!blobModified);
-
- int n = (int) Math.min(blobSize, length - (long)i * blobSize);
- InputStream stream = data.get(i).getNewStream();
- try {
- ByteStreams.readFully(stream, blob, 0, n);
- } finally {
- stream.close();
- }
- index = i;
- }
- }
-
- private void flushBlob() throws IOException {
- if (blobModified) {
- int n = (int) Math.min(blobSize, length - (long)index * blobSize);
- InputStream in = new ByteArrayInputStream(blob, 0, n);
- if (uniqueKey != null) {
- in = new SequenceInputStream(in,
- new ByteArrayInputStream(uniqueKey));
- }
-
- Blob b = blobFactory.createBlob(in);
- if (index < data.size()) {
- data.set(index, b);
- } else {
- checkState(index == data.size());
- data.add(b);
- }
- dataModified = true;
- blobModified = false;
- }
- }
+ void seek(long pos) throws IOException;
/**
* Duplicates this instance to be used by a different consumer/thread.
@@ -205,49 +36,7 @@ class OakIndexFile {
*
* @return cloned instance
*/
- public OakIndexFile clone() {
- return new OakIndexFile(this);
- }
-
- /**
- * @return length of index file
- */
- public long length() {
- return length;
- }
-
- /**
- * @return current location of access
- */
- public long position() {
- return position;
- }
-
- public void close() {
- this.blob = null;
- this.data = null;
- }
-
- public boolean isClosed() {
- return blob == null && data == null;
- }
-
- /**
- * Seek current location of access to {@code pos}
- * @param pos
- * @throws IOException
- */
- public void seek(long pos) throws IOException {
- // seek() may be called with pos == length
- // see https://issues.apache.org/jira/browse/LUCENE-1196
- if (pos < 0 || pos > length) {
- String msg = String.format("Invalid seek request for [%s][%s], " +
- "position: %d, file length: %d", dirDetails, name, pos,
length);
- throw new IOException(msg);
- } else {
- position = pos;
- }
- }
+ OakIndexFile clone();
/**
* Read {@code len} number of bytes from underlying storage and copy them
@@ -257,33 +46,8 @@ class OakIndexFile {
* @param len numeber of bytes to be read from storage
* @throws IOException
*/
- public void readBytes(byte[] b, int offset, int len)
- throws IOException {
- checkPositionIndexes(offset, offset + len, checkNotNull(b).length);
-
- if (len < 0 || position + len > length) {
- String msg = String.format("Invalid byte range request for
[%s][%s], " +
- "position: %d, file length: %d, len: %d", dirDetails,
name, position, length, len);
- throw new IOException(msg);
- }
-
- int i = (int) (position / blobSize);
- int o = (int) (position % blobSize);
- while (len > 0) {
- loadBlob(i);
-
- int l = Math.min(len, blobSize - o);
- System.arraycopy(blob, o, b, offset, l);
-
- offset += l;
- len -= l;
- position += l;
- // next block
- i++;
- // for the next block, we read from the beginning
- o = 0;
- }
- }
+ void readBytes(byte[] b, int offset, int len)
+ throws IOException;
/**
* Writes {@code len} number of bytes from byte array {@code b}
@@ -293,79 +57,13 @@ class OakIndexFile {
* @param len numeber of bytes to be written to storage
* @throws IOException
*/
- public void writeBytes(byte[] b, int offset, int len)
- throws IOException {
- int i = (int) (position / blobSize);
- int o = (int) (position % blobSize);
- while (len > 0) {
- int l = Math.min(len, blobSize - o);
-
- if (index != i) {
- if (o > 0 || (l < blobSize && position + l < length)) {
- // loadBlob first flushes the previous block,
- // and it sets the index
- loadBlob(i);
- } else {
- // we don't need to load the block,
- // as we anyway overwrite it fully, if:
- // o == 0 (start writing at a block boundary)
- // and either: l is the blockSize, or
- // we write at least to the end of the file
- flushBlob();
- index = i;
- }
- }
- System.arraycopy(b, offset, blob, o, l);
- blobModified = true;
-
- offset += l;
- len -= l;
- position += l;
- length = Math.max(length, position);
-
- i++;
- o = 0;
- }
- }
-
- private static int determineBlobSize(NodeBuilder file){
- if (file.hasProperty(OakDirectory.PROP_BLOB_SIZE)){
- return
Ints.checkedCast(file.getProperty(OakDirectory.PROP_BLOB_SIZE).getValue(Type.LONG));
- }
- return DEFAULT_BLOB_SIZE;
- }
-
- private static byte[] readUniqueKey(NodeBuilder file) {
- if (file.hasProperty(OakDirectory.PROP_UNIQUE_KEY)) {
- String key = file.getString(OakDirectory.PROP_UNIQUE_KEY);
- return StringUtils.convertHexToBytes(key);
- }
- return null;
- }
+ void writeBytes(byte[] b, int offset, int len)
+ throws IOException;
/**
* Flushes the content into storage. Before calling this method, written
* content only exist in memory
* @throws IOException
*/
- public void flush() throws IOException {
- flushBlob();
- if (dataModified) {
- file.setProperty(JCR_LASTMODIFIED, System.currentTimeMillis());
- file.setProperty(JCR_DATA, data, BINARIES);
- dataModified = false;
- }
- }
-
- @Override
- public String toString() {
- return name;
- }
-
- /**
- * @return name of the index being accessed
- */
- public String getName() {
- return name;
- }
+ void flush() throws IOException;
}
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexInput.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexInput.java?rev=1810241&r1=1810240&r2=1810241&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexInput.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexInput.java
Sun Oct 1 00:41:46 2017
@@ -35,7 +35,7 @@ class OakIndexInput extends IndexInput {
BlobFactory blobFactory) {
super(name);
this.dirDetails = dirDetails;
- this.file = new OakIndexFile(name, file, dirDetails, blobFactory);
+ this.file = new OakBufferedIndexFile(name, file, dirDetails,
blobFactory);
clones = WeakIdentityMap.newConcurrentHashMap();
}
Modified:
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexOutput.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexOutput.java?rev=1810241&r1=1810240&r2=1810241&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexOutput.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakIndexOutput.java
Sun Oct 1 00:41:46 2017
@@ -28,7 +28,7 @@ final class OakIndexOutput extends Index
public OakIndexOutput(String name, NodeBuilder file, String dirDetails,
BlobFactory blobFactory) throws IOException {
this.dirDetails = dirDetails;
- this.file = new OakIndexFile(name, file, dirDetails, blobFactory);
+ this.file = new OakBufferedIndexFile(name, file, dirDetails,
blobFactory);
}
@Override
Modified:
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakDirectoryTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakDirectoryTest.java?rev=1810241&r1=1810240&r2=1810241&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakDirectoryTest.java
(original)
+++
jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/directory/OakDirectoryTest.java
Sun Oct 1 00:41:46 2017
@@ -57,10 +57,6 @@ import org.apache.jackrabbit.oak.api.Blo
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition;
import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants;
-import
org.apache.jackrabbit.oak.plugins.index.lucene.directory.ActiveDeletedBlobCollectorFactory;
-import org.apache.jackrabbit.oak.plugins.index.lucene.directory.BlobFactory;
-import org.apache.jackrabbit.oak.plugins.index.lucene.directory.OakDirectory;
-import org.apache.jackrabbit.oak.plugins.index.lucene.directory.OakIndexFile;
import org.apache.jackrabbit.oak.plugins.memory.ArrayBasedBlob;
import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
@@ -110,9 +106,9 @@ public class OakDirectoryTest {
@Test
public void testCompatibility() throws Exception{
- builder.setProperty(LuceneIndexConstants.BLOB_SIZE,
OakIndexFile.DEFAULT_BLOB_SIZE);
+ builder.setProperty(LuceneIndexConstants.BLOB_SIZE,
OakBufferedIndexFile.DEFAULT_BLOB_SIZE);
Directory dir = createDir(builder, false, "/foo");
- byte[] data = assertWrites(dir, OakIndexFile.DEFAULT_BLOB_SIZE);
+ byte[] data = assertWrites(dir,
OakBufferedIndexFile.DEFAULT_BLOB_SIZE);
NodeBuilder testNode =
builder.child(INDEX_DATA_CHILD_NAME).child("test");
//Remove the size property to simulate old behaviour