diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlockIndex.java hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlockIndex.java index 270a9b7..236af06 100644 --- hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlockIndex.java +++ hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlockIndex.java @@ -54,8 +54,8 @@ import org.apache.hadoop.util.StringUtils; * ({@link BlockIndexReader}) single-level and multi-level block indexes. * * Examples of how to use the block index writer can be found in - * {@link org.apache.hadoop.hbase.util.CompoundBloomFilterWriter} - * and {@link HFileWriterV2}. Examples of how to use the reader can be + * {@link org.apache.hadoop.hbase.util.CompoundBloomFilterWriter} + * and {@link HFileWriterV2}. Examples of how to use the reader can be * found in {@link HFileReaderV2} and TestHFileBlockIndex. */ @InterfaceAudience.Private @@ -193,7 +193,7 @@ public class HFileBlockIndex { * Return the BlockWithScanInfo which contains the DataBlock with other scan * info such as nextIndexedKey. This function will only be called when the * HFile version is larger than 1. - * + * * @param key * the key we are looking for * @param currentBlock @@ -494,7 +494,7 @@ public class HFileBlockIndex { * Performs a binary search over a non-root level index block. Utilizes the * secondary index, which records the offsets of (offset, onDiskSize, * firstKey) tuples of all entries. - * + * * @param key * the key we are searching for offsets to individual entries in * the blockIndex buffer @@ -641,7 +641,7 @@ public class HFileBlockIndex { } } } - + /** * Read in the root-level index from the given input stream. Must match * what was written into the root level by @@ -865,7 +865,11 @@ public class HFileBlockIndex { : null; if (curInlineChunk != null) { - while (rootChunk.getRootSize() > maxChunkSize) { + while (rootChunk.getRootSize() > maxChunkSize + && rootChunk.getNumEntries() > 1 // HBASE-16288: if firstKey is larger than maxChunkSize + // we will loop indefinitely otherwise. + && numLevels < 16 // Sanity check. + ) { rootChunk = writeIntermediateLevel(out, rootChunk); numLevels += 1; } @@ -956,8 +960,9 @@ public class HFileBlockIndex { curChunk.add(currentLevel.getBlockKey(i), currentLevel.getBlockOffset(i), currentLevel.getOnDiskDataSize(i)); - if (curChunk.getRootSize() >= maxChunkSize) + if (curChunk.getRootSize() >= maxChunkSize) { writeIntermediateBlock(out, parent, curChunk); + } } if (curChunk.getNumEntries() > 0) {