private void readStoreFile(boolean useTags) throws IOException {
    HFile.Reader reader = HFile.createReader(fs, storeFilePath, cacheConf, true, conf);
    LOG.info("HFile information: " + reader);
    HFileContext meta =
      new HFileContextBuilder().withCompression(compress).withBytesPerCheckSum(CKBYTES)
        .withChecksumType(ChecksumType.NULL).withBlockSize(DATA_BLOCK_SIZE)
        .withDataBlockEncoding(NoOpDataBlockEncoder.INSTANCE.getDataBlockEncoding())
        .withIncludesTags(useTags).build();
    final boolean cacheBlocks = false;
    final boolean pread = false;
    HFileScanner scanner = reader.getScanner(conf, cacheBlocks, pread);
    assertTrue(testDescription, scanner.seekTo());

    long offset = 0;
    EnumMap<BlockType, Integer> blockCountByType = new EnumMap<>(BlockType.class);

    DataBlockEncoding encodingInCache = NoOpDataBlockEncoder.INSTANCE.getDataBlockEncoding();
    List<Long> cachedBlocksOffset = new ArrayList<>();
    Map<Long, Pair<HFileBlock, HFileBlock>> cachedBlocks = new HashMap<>();
    while (offset < reader.getTrailer().getLoadOnOpenDataOffset()) {
      // Flags: don't cache the block, use pread, this is not a compaction.
      // Also, pass null for expected block type to avoid checking it.
      HFileBlock block =
        reader.readBlock(offset, -1, false, true, false, true, null, encodingInCache);
      BlockCacheKey blockCacheKey = new BlockCacheKey(reader.getName(), offset);
      HFileBlock fromCache = (HFileBlock) blockCache.getBlock(blockCacheKey, true, false, true);
      boolean isCached = fromCache != null;
      cachedBlocksOffset.add(offset);
      cachedBlocks.put(offset, fromCache == null ? null : Pair.newPair(block, fromCache));
      boolean shouldBeCached = cowType.shouldBeCached(block.getBlockType());
      assertTrue(
        "shouldBeCached: " + shouldBeCached + "\n" + "isCached: " + isCached + "\n"
          + "Test description: " + testDescription + "\n" + "block: " + block + "\n"
          + "encodingInCache: " + encodingInCache + "\n" + "blockCacheKey: " + blockCacheKey,
        shouldBeCached == isCached);
      if (isCached) {
        if (cacheConf.shouldCacheCompressed(fromCache.getBlockType().getCategory())) {
          if (compress != Compression.Algorithm.NONE) {
            assertFalse(fromCache.isUnpacked());
          }
          fromCache = fromCache.unpack(meta, reader.getUncachedBlockReader());
        } else {
          assertTrue(fromCache.isUnpacked());
        }
        // block we cached at write-time and block read from file should be identical
        assertEquals(block.getChecksumType(), fromCache.getChecksumType());
        assertEquals(block.getBlockType(), fromCache.getBlockType());
        assertNotEquals(BlockType.ENCODED_DATA, block.getBlockType());
        assertEquals(block.getOnDiskSizeWithHeader(), fromCache.getOnDiskSizeWithHeader());
        assertEquals(block.getOnDiskSizeWithoutHeader(), fromCache.getOnDiskSizeWithoutHeader());
        assertEquals(block.getUncompressedSizeWithoutHeader(),
          fromCache.getUncompressedSizeWithoutHeader());
      }
      offset += block.getOnDiskSizeWithHeader();
      BlockType bt = block.getBlockType();
      Integer count = blockCountByType.get(bt);
      blockCountByType.put(bt, (count == null ? 0 : count) + 1);
    }

    LOG.info("Block count by type: " + blockCountByType);
    String countByType = blockCountByType.toString();
    if (useTags) {
      assertEquals(
        "{" + BlockType.DATA + "=2663, LEAF_INDEX=297, BLOOM_CHUNK=9, INTERMEDIATE_INDEX=32}",
        countByType);
    } else {
      assertEquals(
        "{" + BlockType.DATA + "=2498, LEAF_INDEX=278, BLOOM_CHUNK=9, INTERMEDIATE_INDEX=31}",
        countByType);
    }

    // iterate all the keyvalue from hfile
    while (scanner.next()) {
      scanner.getCell();
    }
    Iterator<Long> iterator = cachedBlocksOffset.iterator();
    while (iterator.hasNext()) {
      Long entry = iterator.next();
      BlockCacheKey blockCacheKey = new BlockCacheKey(reader.getName(), entry);
      Pair<HFileBlock, HFileBlock> blockPair = cachedBlocks.get(entry);
      if (blockPair != null) {
        // Call return twice because for the isCache cased the counter would have got incremented
        // twice. Notice that here we need to returnBlock with different blocks. see comments in
        // BucketCache#returnBlock.
        blockPair.getSecond().release();
        if (cacheCompressedData) {
          if (
            this.compress == Compression.Algorithm.NONE || cowType == CacheOnWriteType.INDEX_BLOCKS
              || cowType == CacheOnWriteType.BLOOM_BLOCKS
          ) {
            blockPair.getFirst().release();
          }
        } else {
          blockPair.getFirst().release();
        }
      }
    }
    scanner.shipped();
    reader.close();
  }
The number of valid key types possible in a store file
hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheOnWrite.java