|
17 | 17 | */
|
18 | 18 | package org.apache.hadoop.hbase.regionserver;
|
19 | 19 |
|
| 20 | +import static org.apache.hadoop.hbase.io.hfile.bucket.BucketCache.DEFAULT_ERROR_TOLERATION_DURATION; |
20 | 21 | import static org.junit.Assert.assertEquals;
|
21 | 22 | import static org.junit.Assert.fail;
|
22 | 23 |
|
|
46 | 47 | import org.apache.hadoop.hbase.io.hfile.BlockCacheKey;
|
47 | 48 | import org.apache.hadoop.hbase.io.hfile.BlockType;
|
48 | 49 | import org.apache.hadoop.hbase.io.hfile.CacheConfig;
|
| 50 | +import org.apache.hadoop.hbase.io.hfile.CacheTestUtils; |
49 | 51 | import org.apache.hadoop.hbase.io.hfile.HFileContextBuilder;
|
| 52 | +import org.apache.hadoop.hbase.io.hfile.bucket.BucketCache; |
50 | 53 | import org.apache.hadoop.hbase.testclassification.RegionServerTests;
|
51 | 54 | import org.apache.hadoop.hbase.testclassification.SmallTests;
|
52 | 55 | import org.apache.hadoop.hbase.util.Bytes;
|
|
55 | 58 | import org.junit.ClassRule;
|
56 | 59 | import org.junit.Test;
|
57 | 60 | import org.junit.experimental.categories.Category;
|
| 61 | +import org.slf4j.Logger; |
| 62 | +import org.slf4j.LoggerFactory; |
58 | 63 |
|
59 | 64 | /**
|
60 | 65 | * This class is used to test the functionality of the DataTieringManager.
|
@@ -82,6 +87,8 @@ public class TestDataTieringManager {
|
82 | 87 | public static final HBaseClassTestRule CLASS_RULE =
|
83 | 88 | HBaseClassTestRule.forClass(TestDataTieringManager.class);
|
84 | 89 |
|
| 90 | + private static final Logger LOG = LoggerFactory.getLogger(TestDataTieringManager.class); |
| 91 | + |
85 | 92 | private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
|
86 | 93 | private static Configuration defaultConf;
|
87 | 94 | private static FileSystem fs;
|
@@ -218,6 +225,65 @@ public void testColdDataFiles() {
|
218 | 225 | }
|
219 | 226 | }
|
220 | 227 |
|
| 228 | + @Test |
| 229 | + public void testPickColdDataFiles() { |
| 230 | + Map<String, String> coldDataFiles = dataTieringManager.getColdFilesList(); |
| 231 | + assertEquals(1, coldDataFiles.size()); |
| 232 | + // hStoreFiles[3] is the cold file. |
| 233 | + assert(coldDataFiles.containsKey(hStoreFiles.get(3).getFileInfo().getActiveFileName())); |
| 234 | + } |
| 235 | + |
| 236 | + @Test |
| 237 | + public void testBlockEvictions() throws Exception { |
| 238 | + long capacitySize = 64 * 1024; |
| 239 | + int writeThreads = 3; |
| 240 | + int writerQLen = 64; |
| 241 | + int[] bucketSizes = new int[] { 8 * 1024 + 1024 }; |
| 242 | + |
| 243 | + // Setup: Create a bucket cache with lower capacity |
| 244 | + BucketCache bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize, |
| 245 | + 8192, bucketSizes, writeThreads, writerQLen, testDir + "/bucket.persistence", |
| 246 | + DEFAULT_ERROR_TOLERATION_DURATION, defaultConf); |
| 247 | + |
| 248 | + // Create three Cache keys with cold data files and a block with hot data. |
| 249 | + // hStoreFiles.get(3) is a cold data file, while hStoreFiles.get(0) is a hot file. |
| 250 | + List<BlockCacheKey> cacheKeys = new ArrayList<>(); |
| 251 | + cacheKeys.add(new BlockCacheKey(hStoreFiles.get(3).getPath(), 0, true, BlockType.DATA)); |
| 252 | + cacheKeys.add(new BlockCacheKey(hStoreFiles.get(3).getPath(), 8192, true, BlockType.DATA)); |
| 253 | + cacheKeys.add(new BlockCacheKey(hStoreFiles.get(0).getPath(), 0, true, BlockType.DATA)); |
| 254 | + |
| 255 | + // Create dummy data to be cached and fill the cache completely. |
| 256 | + CacheTestUtils.HFileBlockPair[] blocks = CacheTestUtils.generateHFileBlocks(8192, 3); |
| 257 | + |
| 258 | + int blocksIter = 0; |
| 259 | + for(BlockCacheKey key: cacheKeys) { |
| 260 | + bucketCache.cacheBlock(key, blocks[blocksIter++].getBlock()); |
| 261 | + // Ensure that the block is persisted to the file. |
| 262 | + while (!(bucketCache.getBackingMap().containsKey(key))) { |
| 263 | + Thread.sleep(100); |
| 264 | + } |
| 265 | + } |
| 266 | + |
| 267 | + // Verify that the bucket cache contains 4 blocks. |
| 268 | + assertEquals(3, bucketCache.getBackingMap().keySet().size()); |
| 269 | + |
| 270 | + // Add an additional block into cache with hot data which should trigger the eviction |
| 271 | + BlockCacheKey newKey = new BlockCacheKey(hStoreFiles.get(2).getPath(), 0, true, BlockType.DATA); |
| 272 | + CacheTestUtils.HFileBlockPair[] newBlock = CacheTestUtils.generateHFileBlocks(8192, 1); |
| 273 | + |
| 274 | + bucketCache.cacheBlock(newKey, newBlock[0].getBlock()); |
| 275 | + while (!(bucketCache.getBackingMap().containsKey(newKey))) { |
| 276 | + Thread.sleep(100); |
| 277 | + } |
| 278 | + |
| 279 | + // Verify that the bucket cache now contains 2 hot blocks blocks only. |
| 280 | + Set<BlockCacheKey> newKeys = bucketCache.getBackingMap().keySet(); |
| 281 | + assertEquals(2, newKeys.size()); |
| 282 | + for(BlockCacheKey key: newKeys){ |
| 283 | + assert(dataTieringManager.isHotData(key)); |
| 284 | + } |
| 285 | + } |
| 286 | + |
221 | 287 | private void testDataTieringMethodWithPath(DataTieringMethodCallerWithPath caller, Path path,
|
222 | 288 | boolean expectedResult, DataTieringException exception) {
|
223 | 289 | try {
|
|
0 commit comments