Index: src/test/java/org/apache/hadoop/hbase/io/hfile/RandomSeek.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/io/hfile/RandomSeek.java (revision 1190015) +++ src/test/java/org/apache/hadoop/hbase/io/hfile/RandomSeek.java (working copy) @@ -68,7 +68,7 @@ long start = System.currentTimeMillis(); SimpleBlockCache cache = new SimpleBlockCache(); CacheConfig cacheConf = new CacheConfig(cache, true, false, false, false, - false, false, false); + false, false, false, true); Reader reader = HFile.createReader(lfs, path, cacheConf); reader.loadFileInfo(); Index: src/test/java/org/apache/hadoop/hbase/client/TestCacheDatablocks.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/client/TestCacheDatablocks.java (revision 0) +++ src/test/java/org/apache/hadoop/hbase/client/TestCacheDatablocks.java (revision 0) @@ -0,0 +1,97 @@ +package org.apache.hadoop.hbase.client; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertEquals; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.io.hfile.BlockCache; +import org.apache.hadoop.hbase.io.hfile.CacheConfig; +import org.apache.hadoop.hbase.regionserver.HRegion; +import org.apache.hadoop.hbase.regionserver.Store; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * End to end test for disabling caching of data blocks + */ +public class TestCacheDatablocks { + private static HBaseTestingUtility TEST_UTIL; + private static final byte [] ROW = Bytes.toBytes("testRow"); + private static final byte [] FAMILY = Bytes.toBytes("testFamily"); + private static final byte [] QUALIFIER = Bytes.toBytes("testQualifier"); + private static final byte [] VALUE = Bytes.toBytes("testValue"); + + /** + * @throws java.lang.Exception + */ + @BeforeClass + public static void setUpBeforeClass() throws Exception { + Configuration c = HBaseConfiguration.create(); + c.setBoolean(CacheConfig.HFILE_BLOCK_CACHE_DATABLOCKS_KEY, false); + TEST_UTIL = new HBaseTestingUtility(c); + TEST_UTIL.startMiniCluster(); + } + + /** + * @throws java.lang.Exception + */ + @AfterClass + public static void tearDownAfterClass() throws Exception { + TEST_UTIL.shutdownMiniCluster(); + } + + /** + * Make sure that the disabling data block caching in the store, + * and that data bock are in fact not cached. + * @throws Exception + */ + @Test + public void testCacheDataBlocks() throws Exception { + final byte[] tableName = Bytes.toBytes("testCacheDataBlocks"); + HTable t = TEST_UTIL.createTable(tableName, FAMILY); + // get the block cache and region + // (stolen from TestFromClientSide.testCacheOnWriteEvictOnClose) + String regionName = t.getRegionLocations().firstKey().getEncodedName(); + HRegion region = TEST_UTIL.getRSForFirstRegionInTable(tableName) + .getFromOnlineRegions(regionName); + Store store = region.getStores().values().iterator().next(); + CacheConfig cacheConf = store.getCacheConfig(); + // make sure the setting made it through + assertFalse(cacheConf.shouldCacheDatablocks()); + // make sure write caching is off + assertFalse(cacheConf.shouldCacheDataOnWrite()); + BlockCache cache = cacheConf.getBlockCache(); + + long startBlockCount = cache.getBlockCount(); + long startBlockHits = cache.getStats().getHitCount(); + long startBlockMiss = cache.getStats().getMissCount(); + + Put put = new Put(ROW); + put.add(FAMILY, QUALIFIER, VALUE); + t.put(put); + + region.flushcache(); + + assertEquals(startBlockCount, cache.getBlockCount()); + assertEquals(startBlockHits, cache.getStats().getHitCount()); + assertEquals(startBlockMiss, cache.getStats().getMissCount()); + + Get g = new Get(ROW); + region.get(g, null); + + assertEquals(startBlockCount, cache.getBlockCount()); + assertEquals(startBlockHits, cache.getStats().getHitCount()); + // reloaded the datablock once + assertEquals(startBlockMiss+1, cache.getStats().getMissCount()); + + region.get(g, null); + assertEquals(startBlockCount, cache.getBlockCount()); + assertEquals(startBlockHits, cache.getStats().getHitCount()); + // and once more + assertEquals(startBlockMiss+2, cache.getStats().getMissCount()); + } +} Index: src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java (revision 1190015) +++ src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java (working copy) @@ -66,7 +66,8 @@ private StoreScanner(Store store, boolean cacheBlocks, Scan scan, final NavigableSet columns){ this.store = store; - this.cacheBlocks = cacheBlocks; + this.cacheBlocks = cacheBlocks + && (store == null || store.getCacheConfig().shouldCacheDatablocks()); isGet = scan.isGetScan(); int numCol = columns == null ? 0 : columns.size(); explicitColumnQuery = numCol > 0; Index: src/main/java/org/apache/hadoop/hbase/io/hfile/CacheConfig.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/io/hfile/CacheConfig.java (revision 1190015) +++ src/main/java/org/apache/hadoop/hbase/io/hfile/CacheConfig.java (working copy) @@ -74,6 +74,12 @@ public static final String EVICT_BLOCKS_ON_CLOSE_KEY = "hbase.rs.evictblocksonclose"; + /** + * Configuration key to cache data blocks. + */ + public static final String HFILE_BLOCK_CACHE_DATABLOCKS_KEY = + "hfile.block.cache.datablocks"; + // Defaults public static final boolean DEFAULT_CACHE_DATA_ON_READ = true; @@ -83,6 +89,7 @@ public static final boolean DEFAULT_CACHE_BLOOMS_ON_WRITE = false; public static final boolean DEFAULT_EVICT_ON_CLOSE = false; public static final boolean DEFAULT_COMPRESSED_CACHE = false; + public static final boolean DEFAULT_CACHE_DATABLOCKS = true; /** Local reference to the block cache, null if completely disabled */ private final BlockCache blockCache; @@ -112,6 +119,11 @@ private final boolean cacheCompressed; /** + * Whether data blocks should be cached, if false only index blocks are cached + */ + private final boolean cacheDatablocks; + + /** * Create a cache configuration using the specified configuration object and * family descriptor. * @param conf hbase configuration @@ -126,7 +138,8 @@ conf.getBoolean(CACHE_BLOOM_BLOCKS_ON_WRITE_KEY, DEFAULT_CACHE_BLOOMS_ON_WRITE), conf.getBoolean(EVICT_BLOCKS_ON_CLOSE_KEY, DEFAULT_EVICT_ON_CLOSE), - conf.getBoolean(CACHE_DATA_BLOCKS_COMPRESSED_KEY, DEFAULT_COMPRESSED_CACHE) + conf.getBoolean(CACHE_DATA_BLOCKS_COMPRESSED_KEY, DEFAULT_COMPRESSED_CACHE), + conf.getBoolean(HFILE_BLOCK_CACHE_DATABLOCKS_KEY, DEFAULT_CACHE_DATABLOCKS) ); } @@ -143,11 +156,13 @@ conf.getBoolean(CACHE_BLOCKS_ON_WRITE_KEY, DEFAULT_CACHE_DATA_ON_WRITE), conf.getBoolean(CACHE_INDEX_BLOCKS_ON_WRITE_KEY, DEFAULT_CACHE_INDEXES_ON_WRITE), - conf.getBoolean(CACHE_BLOOM_BLOCKS_ON_WRITE_KEY, + conf.getBoolean(CACHE_BLOOM_BLOCKS_ON_WRITE_KEY, DEFAULT_CACHE_BLOOMS_ON_WRITE), conf.getBoolean(EVICT_BLOCKS_ON_CLOSE_KEY, DEFAULT_EVICT_ON_CLOSE), conf.getBoolean(CACHE_DATA_BLOCKS_COMPRESSED_KEY, - DEFAULT_COMPRESSED_CACHE) + DEFAULT_COMPRESSED_CACHE), + conf.getBoolean(HFILE_BLOCK_CACHE_DATABLOCKS_KEY, + DEFAULT_CACHE_DATABLOCKS) ); } @@ -162,12 +177,13 @@ * @param cacheBloomsOnWrite whether blooms should be cached on write * @param evictOnClose whether blocks should be evicted when HFile is closed * @param cacheCompressed whether to store blocks as compressed in the cache + * @param cacheDatablocks whether to cache data blocks */ CacheConfig(final BlockCache blockCache, final boolean cacheDataOnRead, final boolean inMemory, final boolean cacheDataOnWrite, final boolean cacheIndexesOnWrite, final boolean cacheBloomsOnWrite, final boolean evictOnClose, - final boolean cacheCompressed) { + final boolean cacheCompressed, final boolean cacheDatablocks) { this.blockCache = blockCache; this.cacheDataOnRead = cacheDataOnRead; this.inMemory = inMemory; @@ -176,6 +192,7 @@ this.cacheBloomsOnWrite = cacheBloomsOnWrite; this.evictOnClose = evictOnClose; this.cacheCompressed = cacheCompressed; + this.cacheDatablocks = cacheDatablocks; } /** @@ -186,7 +203,7 @@ this(cacheConf.blockCache, cacheConf.cacheDataOnRead, cacheConf.inMemory, cacheConf.cacheDataOnWrite, cacheConf.cacheIndexesOnWrite, cacheConf.cacheBloomsOnWrite, cacheConf.evictOnClose, - cacheConf.cacheCompressed); + cacheConf.cacheCompressed, cacheConf.cacheDatablocks); } /** @@ -213,6 +230,14 @@ } /** + * Returns whether data blocks of this HFile should be cached or not. + * @return true if blocks should be cached, false if not + */ + public boolean shouldCacheDatablocks() { + return isBlockCacheEnabled() && cacheDatablocks; + } + + /** * @return true if blocks in this file should be flagged as in-memory */ public boolean isInMemory() {