001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.mob; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertNotNull; 022 023import java.io.IOException; 024import java.util.Date; 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.fs.FileSystem; 027import org.apache.hadoop.fs.Path; 028import org.apache.hadoop.hbase.HBaseClassTestRule; 029import org.apache.hadoop.hbase.HBaseTestingUtil; 030import org.apache.hadoop.hbase.HConstants; 031import org.apache.hadoop.hbase.KeyValue; 032import org.apache.hadoop.hbase.TableName; 033import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; 034import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 035import org.apache.hadoop.hbase.client.RegionInfo; 036import org.apache.hadoop.hbase.client.RegionInfoBuilder; 037import org.apache.hadoop.hbase.client.TableDescriptor; 038import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 039import org.apache.hadoop.hbase.io.hfile.CacheConfig; 040import org.apache.hadoop.hbase.regionserver.HMobStore; 041import org.apache.hadoop.hbase.regionserver.HRegion; 042import org.apache.hadoop.hbase.regionserver.StoreContext; 043import org.apache.hadoop.hbase.regionserver.StoreFileWriter; 044import org.apache.hadoop.hbase.testclassification.SmallTests; 045import org.apache.hadoop.hbase.util.Bytes; 046import org.apache.hadoop.hbase.util.Pair; 047import org.junit.After; 048import org.junit.Before; 049import org.junit.ClassRule; 050import org.junit.Test; 051import org.junit.experimental.categories.Category; 052 053@Category(SmallTests.class) 054public class TestMobFileCache { 055 056 @ClassRule 057 public static final HBaseClassTestRule CLASS_RULE = 058 HBaseClassTestRule.forClass(TestMobFileCache.class); 059 060 private HBaseTestingUtil UTIL; 061 private HRegion region; 062 private Configuration conf; 063 private MobFileCache mobFileCache; 064 private Date currentDate = new Date(); 065 private static final String TEST_CACHE_SIZE = "2"; 066 private static final int EXPECTED_CACHE_SIZE_ZERO = 0; 067 private static final int EXPECTED_CACHE_SIZE_ONE = 1; 068 private static final int EXPECTED_CACHE_SIZE_TWO = 2; 069 private static final int EXPECTED_CACHE_SIZE_THREE = 3; 070 private static final long EXPECTED_REFERENCE_ONE = 1; 071 private static final long EXPECTED_REFERENCE_TWO = 2; 072 073 private static final String TABLE = "tableName"; 074 private static final String FAMILY1 = "family1"; 075 private static final String FAMILY2 = "family2"; 076 private static final String FAMILY3 = "family3"; 077 078 private static final byte[] ROW = Bytes.toBytes("row"); 079 private static final byte[] ROW2 = Bytes.toBytes("row2"); 080 private static final byte[] VALUE = Bytes.toBytes("value"); 081 private static final byte[] VALUE2 = Bytes.toBytes("value2"); 082 private static final byte[] QF1 = Bytes.toBytes("qf1"); 083 private static final byte[] QF2 = Bytes.toBytes("qf2"); 084 private static final byte[] QF3 = Bytes.toBytes("qf3"); 085 086 @Before 087 public void setUp() throws Exception { 088 UTIL = new HBaseTestingUtil(); 089 conf = UTIL.getConfiguration(); 090 conf.set(MobConstants.MOB_FILE_CACHE_SIZE_KEY, TEST_CACHE_SIZE); 091 TableDescriptorBuilder tableDescriptorBuilder = 092 TableDescriptorBuilder.newBuilder(UTIL.createTableDescriptor( 093 TableName.valueOf("testMobFileCache"), ColumnFamilyDescriptorBuilder.DEFAULT_MIN_VERSIONS, 094 3, HConstants.FOREVER, ColumnFamilyDescriptorBuilder.DEFAULT_KEEP_DELETED)); 095 ColumnFamilyDescriptor columnFamilyDescriptor = ColumnFamilyDescriptorBuilder 096 .newBuilder(Bytes.toBytes(FAMILY1)).setMobEnabled(true).setMobThreshold(0).build(); 097 tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor); 098 columnFamilyDescriptor = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(FAMILY2)) 099 .setMobEnabled(true).setMobThreshold(0).build(); 100 tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor); 101 columnFamilyDescriptor = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(FAMILY3)) 102 .setMobEnabled(true).setMobThreshold(0).build(); 103 tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor); 104 TableDescriptor tableDescriptor = tableDescriptorBuilder.build(); 105 RegionInfo regionInfo = RegionInfoBuilder.newBuilder(tableDescriptor.getTableName()).build(); 106 mobFileCache = new MobFileCache(conf); 107 region = HBaseTestingUtil.createRegionAndWAL(regionInfo, UTIL.getDataTestDir(), conf, 108 tableDescriptor, mobFileCache); 109 } 110 111 @After 112 public void tearDown() throws Exception { 113 region.close(); 114 region.getFilesystem().delete(UTIL.getDataTestDir(), true); 115 } 116 117 /** 118 * Create the mob store file. 119 */ 120 private Pair<Path, StoreContext> createAndGetMobStoreFileContextPair(String family) 121 throws IOException { 122 ColumnFamilyDescriptor columnFamilyDescriptor = ColumnFamilyDescriptorBuilder 123 .newBuilder(Bytes.toBytes(family)).setMaxVersions(4).setMobEnabled(true).build(); 124 // Setting up a Store 125 TableName tn = TableName.valueOf(TABLE); 126 TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(tn); 127 tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor); 128 HMobStore mobStore = (HMobStore) region.getStore(columnFamilyDescriptor.getName()); 129 KeyValue key1 = new KeyValue(ROW, columnFamilyDescriptor.getName(), QF1, 1, VALUE); 130 KeyValue key2 = new KeyValue(ROW, columnFamilyDescriptor.getName(), QF2, 1, VALUE); 131 KeyValue key3 = new KeyValue(ROW2, columnFamilyDescriptor.getName(), QF3, 1, VALUE2); 132 KeyValue[] keys = new KeyValue[] { key1, key2, key3 }; 133 int maxKeyCount = keys.length; 134 RegionInfo regionInfo = RegionInfoBuilder.newBuilder(tn).build(); 135 StoreFileWriter mobWriter = mobStore.createWriterInTmp(currentDate, maxKeyCount, 136 columnFamilyDescriptor.getCompactionCompressionType(), regionInfo.getStartKey(), false); 137 Path mobFilePath = mobWriter.getPath(); 138 String fileName = mobFilePath.getName(); 139 mobWriter.append(key1); 140 mobWriter.append(key2); 141 mobWriter.append(key3); 142 mobWriter.close(); 143 String targetPathName = MobUtils.formatDate(currentDate); 144 Path targetPath = new Path(mobStore.getPath(), targetPathName); 145 mobStore.commitFile(mobFilePath, targetPath); 146 return new Pair(new Path(targetPath, fileName), mobStore.getStoreContext()); 147 } 148 149 @Test 150 public void testMobFileCache() throws Exception { 151 FileSystem fs = FileSystem.get(conf); 152 Pair<Path, StoreContext> fileAndContextPair1 = createAndGetMobStoreFileContextPair(FAMILY1); 153 Pair<Path, StoreContext> fileAndContextPair2 = createAndGetMobStoreFileContextPair(FAMILY2); 154 Pair<Path, StoreContext> fileAndContextPair3 = createAndGetMobStoreFileContextPair(FAMILY3); 155 156 Path file1Path = fileAndContextPair1.getFirst(); 157 Path file2Path = fileAndContextPair2.getFirst(); 158 Path file3Path = fileAndContextPair3.getFirst(); 159 160 CacheConfig cacheConf = new CacheConfig(conf); 161 // Before open one file by the MobFileCache 162 assertEquals(EXPECTED_CACHE_SIZE_ZERO, mobFileCache.getCacheSize()); 163 // Open one file by the MobFileCache 164 CachedMobFile cachedMobFile1 = (CachedMobFile) mobFileCache.openFile(fs, file1Path, cacheConf, 165 fileAndContextPair1.getSecond()); 166 assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize()); 167 assertNotNull(cachedMobFile1); 168 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile1.getReferenceCount()); 169 170 // The evict is also managed by a schedule thread pool. 171 // And its check period is set as 3600 seconds by default. 172 // This evict should get the lock at the most time 173 mobFileCache.evict(); // Cache not full, evict it 174 assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize()); 175 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile1.getReferenceCount()); 176 177 mobFileCache.evictFile(file1Path.getName()); // Evict one file 178 assertEquals(EXPECTED_CACHE_SIZE_ZERO, mobFileCache.getCacheSize()); 179 assertEquals(EXPECTED_REFERENCE_ONE, cachedMobFile1.getReferenceCount()); 180 181 cachedMobFile1.close(); // Close the cached mob file 182 183 // Reopen three cached file 184 cachedMobFile1 = (CachedMobFile) mobFileCache.openFile(fs, file1Path, cacheConf, 185 fileAndContextPair1.getSecond()); 186 assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize()); 187 CachedMobFile cachedMobFile2 = (CachedMobFile) mobFileCache.openFile(fs, file2Path, cacheConf, 188 fileAndContextPair2.getSecond()); 189 assertEquals(EXPECTED_CACHE_SIZE_TWO, mobFileCache.getCacheSize()); 190 CachedMobFile cachedMobFile3 = (CachedMobFile) mobFileCache.openFile(fs, file3Path, cacheConf, 191 fileAndContextPair3.getSecond()); 192 // Before the evict 193 // Evict the cache, should close the first file 1 194 assertEquals(EXPECTED_CACHE_SIZE_THREE, mobFileCache.getCacheSize()); 195 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile1.getReferenceCount()); 196 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile2.getReferenceCount()); 197 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile3.getReferenceCount()); 198 mobFileCache.evict(); 199 assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize()); 200 assertEquals(EXPECTED_REFERENCE_ONE, cachedMobFile1.getReferenceCount()); 201 assertEquals(EXPECTED_REFERENCE_ONE, cachedMobFile2.getReferenceCount()); 202 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile3.getReferenceCount()); 203 } 204}