You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by te...@apache.org on 2011/10/02 23:18:53 UTC
svn commit: r1178256 - in /hbase/branches/0.92: ./
src/main/java/org/apache/hadoop/hbase/io/hfile/
src/test/java/org/apache/hadoop/hbase/io/hfile/
Author: tedyu
Date: Sun Oct 2 21:18:52 2011
New Revision: 1178256
URL: http://svn.apache.org/viewvc?rev=1178256&view=rev
Log:
HBASE-4496 HFile V2 does not honor setCacheBlocks when scanning (Lars and Mikhail)
Modified:
hbase/branches/0.92/CHANGES.txt
hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFile.java
hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlock.java
hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlockIndex.java
hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV1.java
hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java
hbase/branches/0.92/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheOnWrite.java
hbase/branches/0.92/src/test/java/org/apache/hadoop/hbase/io/hfile/TestHFileBlockIndex.java
Modified: hbase/branches/0.92/CHANGES.txt
URL: http://svn.apache.org/viewvc/hbase/branches/0.92/CHANGES.txt?rev=1178256&r1=1178255&r2=1178256&view=diff
==============================================================================
--- hbase/branches/0.92/CHANGES.txt (original)
+++ hbase/branches/0.92/CHANGES.txt Sun Oct 2 21:18:52 2011
@@ -316,6 +316,7 @@ Release 0.92.0 - Unreleased
(Mikhail Bautin)
HBASE-4209 The HBase hbase-daemon.sh SIGKILLs master when stopping it
(Roman Shaposhnik)
+ HBASE-4496 HFile V2 does not honor setCacheBlocks when scanning (Lars and Mikhail)
TESTS
HBASE-4492 TestRollingRestart fails intermittently
Modified: hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFile.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFile.java?rev=1178256&r1=1178255&r2=1178256&view=diff
==============================================================================
--- hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFile.java (original)
+++ hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFile.java Sun Oct 2 21:18:52 2011
@@ -263,63 +263,65 @@ public class HFile {
public static final String CACHE_BLOCKS_ON_WRITE_KEY =
"hbase.rs.cacheblocksonwrite";
- /** An interface used by clients to open and iterate an {@link HFile}. */
- public interface Reader extends Closeable {
+ /** An abstraction used by the block index */
+ public interface CachingBlockReader {
+ HFileBlock readBlock(long offset, long onDiskBlockSize,
+ boolean cacheBlock, final boolean pread, final boolean isCompaction)
+ throws IOException;
+ }
+ /** An interface used by clients to open and iterate an {@link HFile}. */
+ public interface Reader extends Closeable, CachingBlockReader {
/**
* Returns this reader's "name". Usually the last component of the path.
* Needs to be constant as the file is being moved to support caching on
* write.
*/
- String getName();
+ String getName();
- String getColumnFamilyName();
+ String getColumnFamilyName();
- RawComparator<byte []> getComparator();
+ RawComparator<byte []> getComparator();
- HFileScanner getScanner(boolean cacheBlocks,
+ HFileScanner getScanner(boolean cacheBlocks,
final boolean pread, final boolean isCompaction);
- ByteBuffer getMetaBlock(String metaBlockName,
+ ByteBuffer getMetaBlock(String metaBlockName,
boolean cacheBlock) throws IOException;
- HFileBlock readBlock(long offset, int onDiskBlockSize,
- boolean cacheBlock, final boolean pread, final boolean isCompaction)
- throws IOException;
-
- Map<byte[], byte[]> loadFileInfo() throws IOException;
+ Map<byte[], byte[]> loadFileInfo() throws IOException;
- byte[] getLastKey();
+ byte[] getLastKey();
- byte[] midkey() throws IOException;
+ byte[] midkey() throws IOException;
- long length();
+ long length();
- long getEntries();
+ long getEntries();
- byte[] getFirstKey();
+ byte[] getFirstKey();
- long indexSize();
+ long indexSize();
- byte[] getFirstRowKey();
+ byte[] getFirstRowKey();
- byte[] getLastRowKey();
+ byte[] getLastRowKey();
- FixedFileTrailer getTrailer();
+ FixedFileTrailer getTrailer();
- HFileBlockIndex.BlockIndexReader getDataBlockIndexReader();
+ HFileBlockIndex.BlockIndexReader getDataBlockIndexReader();
- HFileScanner getScanner(boolean cacheBlocks, boolean pread);
+ HFileScanner getScanner(boolean cacheBlocks, boolean pread);
- Compression.Algorithm getCompressionAlgorithm();
+ Compression.Algorithm getCompressionAlgorithm();
/**
* Retrieves Bloom filter metadata as appropriate for each {@link HFile}
* version. Knows nothing about how that metadata is structured.
*/
- DataInput getBloomFilterMetadata() throws IOException;
+ DataInput getBloomFilterMetadata() throws IOException;
- Path getPath();
+ Path getPath();
}
private static Reader pickReaderVersion(Path path, FSDataInputStream fsdis,
Modified: hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlock.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlock.java?rev=1178256&r1=1178255&r2=1178256&view=diff
==============================================================================
--- hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlock.java (original)
+++ hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlock.java Sun Oct 2 21:18:52 2011
@@ -921,11 +921,9 @@ public class HFileBlock implements Cache
DataInputStream nextBlockAsStream(BlockType blockType) throws IOException;
}
- /**
- * Just the basic ability to read blocks, providing optional hints of
- * on-disk-size and/or uncompressed size.
- */
- public interface BasicReader {
+ /** A full-fledged reader with iteration ability. */
+ public interface FSReader {
+
/**
* Reads the block at the given offset in the file with the given on-disk
* size and uncompressed size.
@@ -939,10 +937,6 @@ public class HFileBlock implements Cache
*/
HFileBlock readBlockData(long offset, long onDiskSize,
int uncompressedSize, boolean pread) throws IOException;
- }
-
- /** A full-fledged reader with an iteration ability. */
- public interface FSReader extends BasicReader {
/**
* Creates a block iterator over the given portion of the {@link HFile}.
Modified: hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlockIndex.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlockIndex.java?rev=1178256&r1=1178255&r2=1178256&view=diff
==============================================================================
--- hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlockIndex.java (original)
+++ hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlockIndex.java Sun Oct 2 21:18:52 2011
@@ -38,6 +38,7 @@ import org.apache.hadoop.conf.Configurat
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.io.HeapSize;
+import org.apache.hadoop.hbase.io.hfile.HFile.CachingBlockReader;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.ClassSize;
import org.apache.hadoop.hbase.util.CompoundBloomFilterWriter;
@@ -132,12 +133,12 @@ public class HFileBlockIndex {
private int searchTreeLevel;
/** A way to read {@link HFile} blocks at a given offset */
- private HFileBlock.BasicReader blockReader;
+ private CachingBlockReader cachingBlockReader;
public BlockIndexReader(final RawComparator<byte[]> c, final int treeLevel,
- final HFileBlock.BasicReader blockReader) {
+ final CachingBlockReader cachingBlockReader) {
this(c, treeLevel);
- this.blockReader = blockReader;
+ this.cachingBlockReader = cachingBlockReader;
}
public BlockIndexReader(final RawComparator<byte[]> c, final int treeLevel)
@@ -176,7 +177,8 @@ public class HFileBlockIndex {
* @throws IOException
*/
public HFileBlock seekToDataBlock(final byte[] key, int keyOffset,
- int keyLength, HFileBlock currentBlock)
+ int keyLength, HFileBlock currentBlock, boolean cacheBlocks,
+ boolean pread, boolean isCompaction)
throws IOException {
int rootLevelIndex = rootBlockContainingKey(key, keyOffset, keyLength);
if (rootLevelIndex < 0 || rootLevelIndex >= blockOffsets.length) {
@@ -188,23 +190,44 @@ public class HFileBlockIndex {
int currentOnDiskSize = blockDataSizes[rootLevelIndex];
int lookupLevel = 1; // How many levels deep we are in our lookup.
- HFileBlock block = blockReader.readBlockData(currentOffset,
- currentOnDiskSize, -1, true);
- if (block == null) {
- throw new IOException("Failed to read block at offset " +
- currentOffset + ", onDiskSize=" + currentOnDiskSize);
- }
- while (!block.getBlockType().equals(BlockType.DATA)) {
- // Read the block. It may be intermediate level block, leaf level block
- // or data block. In any case, we expect non-root index block format.
- // We don't allow more than searchTreeLevel iterations of this loop.
+ HFileBlock block;
+ while (true) {
+
+ if (currentBlock != null && currentBlock.getOffset() == currentOffset)
+ {
+ // Avoid reading the same block again, even with caching turned off.
+ // This is crucial for compaction-type workload which might have
+ // caching turned off. This is like a one-block cache inside the
+ // scanner.
+ block = currentBlock;
+ } else {
+ // Call HFile's caching block reader API. We always cache index
+ // blocks, otherwise we might get terrible performance.
+ boolean shouldCache = cacheBlocks || (lookupLevel < searchTreeLevel);
+ block = cachingBlockReader.readBlock(currentOffset, currentOnDiskSize,
+ shouldCache, pread, isCompaction);
+ }
+
+ if (block == null) {
+ throw new IOException("Failed to read block at offset " +
+ currentOffset + ", onDiskSize=" + currentOnDiskSize);
+ }
+
+ // Found a data block, break the loop and check our level in the tree.
+ if (block.getBlockType().equals(BlockType.DATA)) {
+ break;
+ }
+
+ // Not a data block. This must be a leaf-level or intermediate-level
+ // index block. We don't allow going deeper than searchTreeLevel.
if (++lookupLevel > searchTreeLevel) {
- throw new IOException("Search Tree Level overflow: lookupLevel: "+
- lookupLevel + " searchTreeLevel: " + searchTreeLevel);
+ throw new IOException("Search Tree Level overflow: lookupLevel="+
+ lookupLevel + ", searchTreeLevel=" + searchTreeLevel);
}
- // read to the byte buffer
+ // Locate the entry corresponding to the given key in the non-root
+ // (leaf or intermediate-level) index block.
ByteBuffer buffer = block.getBufferWithoutHeader();
if (!locateNonRootIndexEntry(buffer, key, keyOffset, keyLength,
comparator)) {
@@ -216,16 +239,6 @@ public class HFileBlockIndex {
currentOffset = buffer.getLong();
currentOnDiskSize = buffer.getInt();
-
- // Located a deeper-level block, now read it.
- if (currentBlock != null && currentBlock.getOffset() == currentOffset)
- {
- // Avoid reading the same block.
- block = currentBlock;
- } else {
- block = blockReader.readBlockData(currentOffset, currentOnDiskSize,
- -1, true);
- }
}
if (lookupLevel != searchTreeLevel) {
@@ -252,12 +265,15 @@ public class HFileBlockIndex {
return midKey;
if (midLeafBlockOffset >= 0) {
- if (blockReader == null) {
+ if (cachingBlockReader == null) {
throw new IOException("Have to read the middle leaf block but " +
"no block reader available");
}
- HFileBlock midLeafBlock = blockReader.readBlockData(
- midLeafBlockOffset, midLeafBlockOnDiskSize, -1, true);
+
+ // Caching, using pread, assuming this is not a compaction.
+ HFileBlock midLeafBlock = cachingBlockReader.readBlock(
+ midLeafBlockOffset, midLeafBlockOnDiskSize, true, true, false);
+
ByteBuffer b = midLeafBlock.getBufferWithoutHeader();
int numDataBlocks = b.getInt();
int keyRelOffset = b.getInt(Bytes.SIZEOF_INT * (midKeyEntry + 1));
Modified: hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV1.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV1.java?rev=1178256&r1=1178255&r2=1178256&view=diff
==============================================================================
--- hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV1.java (original)
+++ hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV1.java Sun Oct 2 21:18:52 2011
@@ -643,7 +643,7 @@ public class HFileReaderV1 extends Abstr
}
@Override
- public HFileBlock readBlock(long offset, int onDiskBlockSize,
+ public HFileBlock readBlock(long offset, long onDiskBlockSize,
boolean cacheBlock, boolean pread, boolean isCompaction) {
throw new UnsupportedOperationException();
}
Modified: hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java?rev=1178256&r1=1178255&r2=1178256&view=diff
==============================================================================
--- hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java (original)
+++ hbase/branches/0.92/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java Sun Oct 2 21:18:52 2011
@@ -37,8 +37,7 @@ import org.apache.hadoop.hbase.util.IdLo
/**
* {@link HFile} reader for version 2.
*/
-public class HFileReaderV2 extends AbstractHFileReader implements
- HFileBlock.BasicReader {
+public class HFileReaderV2 extends AbstractHFileReader {
private static final Log LOG = LogFactory.getLog(HFileReaderV2.class);
@@ -203,23 +202,6 @@ public class HFileReaderV2 extends Abstr
}
/**
- * Implements the "basic block reader" API, used mainly by
- * {@link HFileBlockIndex.BlockIndexReader} in
- * {@link HFileBlockIndex.BlockIndexReader#seekToDataBlock(byte[], int, int,
- * HFileBlock)} in a random-read access pattern.
- */
- @Override
- public HFileBlock readBlockData(long offset, long onDiskSize,
- int uncompressedSize, boolean pread) throws IOException {
- if (onDiskSize >= Integer.MAX_VALUE) {
- throw new IOException("Invalid on-disk size: " + onDiskSize);
- }
-
- // Assuming we are not doing a compaction.
- return readBlock(offset, (int) onDiskSize, true, pread, false);
- }
-
- /**
* Read in a file block.
*
* @param dataBlockOffset offset to read.
@@ -231,7 +213,7 @@ public class HFileReaderV2 extends Abstr
* @throws IOException
*/
@Override
- public HFileBlock readBlock(long dataBlockOffset, int onDiskBlockSize,
+ public HFileBlock readBlock(long dataBlockOffset, long onDiskBlockSize,
boolean cacheBlock, boolean pread, final boolean isCompaction)
throws IOException {
if (dataBlockIndexReader == null) {
@@ -498,9 +480,11 @@ public class HFileReaderV2 extends Abstr
*/
private int seekTo(byte[] key, int offset, int length, boolean rewind)
throws IOException {
- HFileBlock seekToBlock =
- ((HFileReaderV2) reader).getDataBlockIndexReader().seekToDataBlock(
- key, offset, length, block);
+ HFileBlockIndex.BlockIndexReader indexReader =
+ reader.getDataBlockIndexReader();
+ HFileBlock seekToBlock = indexReader.seekToDataBlock(key, offset, length,
+ block, cacheBlocks, pread, isCompaction);
+
if (seekToBlock == null) {
// This happens if the key e.g. falls before the beginning of the file.
return -1;
@@ -665,10 +649,9 @@ public class HFileReaderV2 extends Abstr
@Override
public boolean seekBefore(byte[] key, int offset, int length)
throws IOException {
- HFileReaderV2 reader2 = (HFileReaderV2) reader;
HFileBlock seekToBlock =
- reader2.getDataBlockIndexReader().seekToDataBlock(
- key, offset, length, block);
+ reader.getDataBlockIndexReader().seekToDataBlock(key, offset,
+ length, block, cacheBlocks, pread, isCompaction);
if (seekToBlock == null) {
return false;
}
@@ -686,8 +669,9 @@ public class HFileReaderV2 extends Abstr
// It is important that we compute and pass onDiskSize to the block
// reader so that it does not have to read the header separately to
// figure out the size.
- seekToBlock = reader2.fsBlockReader.readBlockData(previousBlockOffset,
- seekToBlock.getOffset() - previousBlockOffset, -1, pread);
+ seekToBlock = reader.readBlock(previousBlockOffset,
+ seekToBlock.getOffset() - previousBlockOffset, cacheBlocks,
+ pread, isCompaction);
// TODO shortcut: seek forward in this block to the last key of the
// block.
Modified: hbase/branches/0.92/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheOnWrite.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.92/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheOnWrite.java?rev=1178256&r1=1178255&r2=1178256&view=diff
==============================================================================
--- hbase/branches/0.92/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheOnWrite.java (original)
+++ hbase/branches/0.92/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheOnWrite.java Sun Oct 2 21:18:52 2011
@@ -163,8 +163,13 @@ public class TestCacheOnWrite {
new EnumMap<BlockType, Integer>(BlockType.class);
while (offset < reader.getTrailer().getLoadOnOpenDataOffset()) {
- HFileBlock block = reader.readBlockData(offset, prevBlock == null ? -1
- : prevBlock.getNextBlockOnDiskSizeWithHeader(), -1, false);
+ long onDiskSize = -1;
+ if (prevBlock != null) {
+ onDiskSize = prevBlock.getNextBlockOnDiskSizeWithHeader();
+ }
+ // Flags: cache the block, use pread, this is not a compaction.
+ HFileBlock block = reader.readBlock(offset, onDiskSize, true, true,
+ false);
String blockCacheKey = HFile.getBlockCacheKey(reader.getName(), offset);
boolean isCached = blockCache.getBlock(blockCacheKey, true) != null;
boolean shouldBeCached = cowType.shouldBeCached(block.getBlockType());
Modified: hbase/branches/0.92/src/test/java/org/apache/hadoop/hbase/io/hfile/TestHFileBlockIndex.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.92/src/test/java/org/apache/hadoop/hbase/io/hfile/TestHFileBlockIndex.java?rev=1178256&r1=1178255&r2=1178256&view=diff
==============================================================================
--- hbase/branches/0.92/src/test/java/org/apache/hadoop/hbase/io/hfile/TestHFileBlockIndex.java (original)
+++ hbase/branches/0.92/src/test/java/org/apache/hadoop/hbase/io/hfile/TestHFileBlockIndex.java Sun Oct 2 21:18:52 2011
@@ -43,6 +43,7 @@ import org.apache.hadoop.hbase.HBaseTest
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.io.hfile.HFileBlockIndex.BlockIndexReader;
import org.apache.hadoop.hbase.io.hfile.HFileBlockIndex.BlockIndexChunk;
+import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.regionserver.StoreFile;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.ClassSize;
@@ -121,37 +122,36 @@ public class TestHFileBlockIndex {
* A wrapper around a block reader which only caches the results of the last
* operation. Not thread-safe.
*/
- private static class BlockReaderWrapper implements HFileBlock.BasicReader {
+ private static class BlockReaderWrapper implements HFile.CachingBlockReader {
- private HFileBlock.BasicReader realReader;
+ private HFileBlock.FSReader realReader;
private long prevOffset;
private long prevOnDiskSize;
- private long prevUncompressedSize;
private boolean prevPread;
private HFileBlock prevBlock;
public int hitCount = 0;
public int missCount = 0;
- public BlockReaderWrapper(HFileBlock.BasicReader realReader) {
+ public BlockReaderWrapper(HFileBlock.FSReader realReader) {
this.realReader = realReader;
}
@Override
- public HFileBlock readBlockData(long offset, long onDiskSize,
- int uncompressedSize, boolean pread) throws IOException {
+ public HFileBlock readBlock(long offset, long onDiskSize,
+ boolean cacheBlock, boolean pread, boolean isCompaction)
+ throws IOException {
if (offset == prevOffset && onDiskSize == prevOnDiskSize &&
- uncompressedSize == prevUncompressedSize && pread == prevPread) {
+ pread == prevPread) {
hitCount += 1;
return prevBlock;
}
missCount += 1;
prevBlock = realReader.readBlockData(offset, onDiskSize,
- uncompressedSize, pread);
+ -1, pread);
prevOffset = offset;
prevOnDiskSize = onDiskSize;
- prevUncompressedSize = uncompressedSize;
prevPread = pread;
return prevBlock;
@@ -182,7 +182,8 @@ public class TestHFileBlockIndex {
for (byte[] key : keys) {
assertTrue(key != null);
assertTrue(indexReader != null);
- HFileBlock b = indexReader.seekToDataBlock(key, 0, key.length, null);
+ HFileBlock b = indexReader.seekToDataBlock(key, 0, key.length, null,
+ true, true, false);
if (Bytes.BYTES_RAWCOMPARATOR.compare(key, firstKeyInFile) < 0) {
assertTrue(b == null);
++i;