Index: hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java (revision 1408122) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileReaderV2.java (working copy) @@ -34,7 +34,6 @@ import org.apache.hadoop.hbase.fs.HFileSystem; import org.apache.hadoop.hbase.io.encoding.DataBlockEncoder; import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding; -import org.apache.hadoop.hbase.io.hfile.BlockType.BlockCategory; import org.apache.hadoop.hbase.io.hfile.HFile.FileInfo; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.IdLock; @@ -286,66 +285,75 @@ new BlockCacheKey(name, dataBlockOffset, dataBlockEncoder.getEffectiveEncodingInCache(isCompaction), expectedBlockType); - IdLock.Entry lockEntry = offsetLock.getLockEntry(dataBlockOffset); + + boolean useLock = false; + IdLock.Entry lockEntry = null; + blockLoads.incrementAndGet(); try { - blockLoads.incrementAndGet(); + while (true) { - // Check cache for block. If found return. - if (cacheConf.isBlockCacheEnabled()) { - HFileBlock cachedBlock = (HFileBlock) - cacheConf.getBlockCache().getBlock(cacheKey, cacheBlock); - if (cachedBlock != null) { - BlockCategory blockCategory = - cachedBlock.getBlockType().getCategory(); - cacheHits.incrementAndGet(); + if (useLock) { + lockEntry = offsetLock.getLockEntry(dataBlockOffset); + } + // Check cache for block. If found return. + if (cacheConf.isBlockCacheEnabled()) { + // Try and get the block from the block cache. If the useLock variable is true then this + // is the second time through the loop and it should not be counted as a block cache miss. + HFileBlock cachedBlock = (HFileBlock) cacheConf.getBlockCache().getBlock(cacheKey, + !useLock && cacheBlock); + if (cachedBlock != null) { + cacheHits.incrementAndGet(); - if (cachedBlock.getBlockType() == BlockType.DATA) { - HFile.dataBlockReadCnt.incrementAndGet(); - } + if (cachedBlock.getBlockType() == BlockType.DATA) { + HFile.dataBlockReadCnt.incrementAndGet(); + } - validateBlockType(cachedBlock, expectedBlockType); + validateBlockType(cachedBlock, expectedBlockType); - // Validate encoding type for encoded blocks. We include encoding - // type in the cache key, and we expect it to match on a cache hit. - if (cachedBlock.getBlockType() == BlockType.ENCODED_DATA && - cachedBlock.getDataBlockEncoding() != - dataBlockEncoder.getEncodingInCache()) { - throw new IOException("Cached block under key " + cacheKey + " " + - "has wrong encoding: " + cachedBlock.getDataBlockEncoding() + - " (expected: " + dataBlockEncoder.getEncodingInCache() + ")"); + // Validate encoding type for encoded blocks. We include encoding + // type in the cache key, and we expect it to match on a cache hit. + if (cachedBlock.getBlockType() == BlockType.ENCODED_DATA + && cachedBlock.getDataBlockEncoding() != dataBlockEncoder.getEncodingInCache()) { + throw new IOException("Cached block under key " + cacheKey + " " + + "has wrong encoding: " + cachedBlock.getDataBlockEncoding() + " (expected: " + + dataBlockEncoder.getEncodingInCache() + ")"); + } + return cachedBlock; } - return cachedBlock; + // Carry on, please load. } - // Carry on, please load. - } + if (!useLock) { + // check cache again with lock + useLock = true; + continue; + } - // Load block from filesystem. - long startTimeNs = System.nanoTime(); - HFileBlock hfileBlock = fsBlockReader.readBlockData(dataBlockOffset, - onDiskBlockSize, -1, pread); - hfileBlock = dataBlockEncoder.diskToCacheFormat(hfileBlock, - isCompaction); - validateBlockType(hfileBlock, expectedBlockType); - BlockCategory blockCategory = hfileBlock.getBlockType().getCategory(); + // Load block from filesystem. + long startTimeNs = System.nanoTime(); + HFileBlock hfileBlock = fsBlockReader.readBlockData(dataBlockOffset, onDiskBlockSize, -1, + pread); + hfileBlock = dataBlockEncoder.diskToCacheFormat(hfileBlock, isCompaction); + validateBlockType(hfileBlock, expectedBlockType); - final long delta = System.nanoTime() - startTimeNs; - HFile.offerReadLatency(delta, pread); + final long delta = System.nanoTime() - startTimeNs; + HFile.offerReadLatency(delta, pread); - // Cache the block if necessary - if (cacheBlock && cacheConf.shouldCacheBlockOnRead( - hfileBlock.getBlockType().getCategory())) { - cacheConf.getBlockCache().cacheBlock(cacheKey, hfileBlock, - cacheConf.isInMemory()); - } + // Cache the block if necessary + if (cacheBlock && cacheConf.shouldCacheBlockOnRead(hfileBlock.getBlockType().getCategory())) { + cacheConf.getBlockCache().cacheBlock(cacheKey, hfileBlock, cacheConf.isInMemory()); + } - if (hfileBlock.getBlockType() == BlockType.DATA) { - HFile.dataBlockReadCnt.incrementAndGet(); + if (hfileBlock.getBlockType() == BlockType.DATA) { + HFile.dataBlockReadCnt.incrementAndGet(); + } + + return hfileBlock; } - - return hfileBlock; } finally { - offsetLock.releaseLockEntry(lockEntry); + if (lockEntry != null) { + offsetLock.releaseLockEntry(lockEntry); + } } }