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.HBaseConfiguration; 030import org.apache.hadoop.hbase.HBaseTestingUtility; 031import org.apache.hadoop.hbase.HColumnDescriptor; 032import org.apache.hadoop.hbase.HRegionInfo; 033import org.apache.hadoop.hbase.HTableDescriptor; 034import org.apache.hadoop.hbase.KeyValue; 035import org.apache.hadoop.hbase.TableName; 036import org.apache.hadoop.hbase.client.RegionInfo; 037import org.apache.hadoop.hbase.client.RegionInfoBuilder; 038import org.apache.hadoop.hbase.io.hfile.CacheConfig; 039import org.apache.hadoop.hbase.regionserver.HMobStore; 040import org.apache.hadoop.hbase.regionserver.HRegion; 041import org.apache.hadoop.hbase.regionserver.StoreFileWriter; 042import org.apache.hadoop.hbase.testclassification.SmallTests; 043import org.apache.hadoop.hbase.util.Bytes; 044import org.junit.After; 045import org.junit.Before; 046import org.junit.ClassRule; 047import org.junit.Test; 048import org.junit.experimental.categories.Category; 049import org.slf4j.Logger; 050import org.slf4j.LoggerFactory; 051 052@Category(SmallTests.class) 053public class TestMobFileCache { 054 055 @ClassRule 056 public static final HBaseClassTestRule CLASS_RULE = 057 HBaseClassTestRule.forClass(TestMobFileCache.class); 058 059 static final Logger LOG = LoggerFactory.getLogger(TestMobFileCache.class); 060 private HBaseTestingUtility 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 = HBaseTestingUtility.createLocalHTU(); 089 conf = UTIL.getConfiguration(); 090 conf.set(MobConstants.MOB_FILE_CACHE_SIZE_KEY, TEST_CACHE_SIZE); 091 HTableDescriptor htd = UTIL.createTableDescriptor("testMobFileCache"); 092 HColumnDescriptor hcd1 = new HColumnDescriptor(FAMILY1); 093 hcd1.setMobEnabled(true); 094 hcd1.setMobThreshold(0); 095 HColumnDescriptor hcd2 = new HColumnDescriptor(FAMILY2); 096 hcd2.setMobEnabled(true); 097 hcd2.setMobThreshold(0); 098 HColumnDescriptor hcd3 = new HColumnDescriptor(FAMILY3); 099 hcd3.setMobEnabled(true); 100 hcd3.setMobThreshold(0); 101 htd.addFamily(hcd1); 102 htd.addFamily(hcd2); 103 htd.addFamily(hcd3); 104 RegionInfo regionInfo = RegionInfoBuilder.newBuilder(htd.getTableName()).build(); 105 mobFileCache = new MobFileCache(conf); 106 region = HBaseTestingUtility.createRegionAndWAL(regionInfo, UTIL.getDataTestDir(), conf, htd, 107 mobFileCache); 108 } 109 110 @After 111 public void tearDown() throws Exception { 112 region.close(); 113 region.getFilesystem().delete(UTIL.getDataTestDir(), true); 114 } 115 116 /** 117 * Create the mob store file. 118 */ 119 private Path createMobStoreFile(String family) throws IOException { 120 return createMobStoreFile(HBaseConfiguration.create(), family); 121 } 122 123 /** 124 * Create the mob store file 125 */ 126 private Path createMobStoreFile(Configuration conf, String family) throws IOException { 127 HColumnDescriptor hcd = new HColumnDescriptor(family); 128 hcd.setMaxVersions(4); 129 hcd.setMobEnabled(true); 130 return createMobStoreFile(hcd); 131 } 132 133 /** 134 * Create the mob store file 135 */ 136 private Path createMobStoreFile(HColumnDescriptor hcd) throws IOException { 137 // Setting up a Store 138 TableName tn = TableName.valueOf(TABLE); 139 HTableDescriptor htd = new HTableDescriptor(tn); 140 htd.addFamily(hcd); 141 HMobStore mobStore = (HMobStore) region.getStore(hcd.getName()); 142 KeyValue key1 = new KeyValue(ROW, hcd.getName(), QF1, 1, VALUE); 143 KeyValue key2 = new KeyValue(ROW, hcd.getName(), QF2, 1, VALUE); 144 KeyValue key3 = new KeyValue(ROW2, hcd.getName(), QF3, 1, VALUE2); 145 KeyValue[] keys = new KeyValue[] { key1, key2, key3 }; 146 int maxKeyCount = keys.length; 147 HRegionInfo regionInfo = new HRegionInfo(tn); 148 StoreFileWriter mobWriter = mobStore.createWriterInTmp(currentDate, maxKeyCount, 149 hcd.getCompactionCompression(), regionInfo.getStartKey(), false); 150 Path mobFilePath = mobWriter.getPath(); 151 String fileName = mobFilePath.getName(); 152 mobWriter.append(key1); 153 mobWriter.append(key2); 154 mobWriter.append(key3); 155 mobWriter.close(); 156 String targetPathName = MobUtils.formatDate(currentDate); 157 Path targetPath = new Path(mobStore.getPath(), targetPathName); 158 mobStore.commitFile(mobFilePath, targetPath); 159 return new Path(targetPath, fileName); 160 } 161 162 @Test 163 public void testMobFileCache() throws Exception { 164 FileSystem fs = FileSystem.get(conf); 165 Path file1Path = createMobStoreFile(FAMILY1); 166 Path file2Path = createMobStoreFile(FAMILY2); 167 Path file3Path = createMobStoreFile(FAMILY3); 168 169 CacheConfig cacheConf = new CacheConfig(conf); 170 // Before open one file by the MobFileCache 171 assertEquals(EXPECTED_CACHE_SIZE_ZERO, mobFileCache.getCacheSize()); 172 // Open one file by the MobFileCache 173 CachedMobFile cachedMobFile1 = (CachedMobFile) mobFileCache.openFile(fs, file1Path, cacheConf); 174 assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize()); 175 assertNotNull(cachedMobFile1); 176 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile1.getReferenceCount()); 177 178 // The evict is also managed by a schedule thread pool. 179 // And its check period is set as 3600 seconds by default. 180 // This evict should get the lock at the most time 181 mobFileCache.evict(); // Cache not full, evict it 182 assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize()); 183 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile1.getReferenceCount()); 184 185 mobFileCache.evictFile(file1Path.getName()); // Evict one file 186 assertEquals(EXPECTED_CACHE_SIZE_ZERO, mobFileCache.getCacheSize()); 187 assertEquals(EXPECTED_REFERENCE_ONE, cachedMobFile1.getReferenceCount()); 188 189 cachedMobFile1.close(); // Close the cached mob file 190 191 // Reopen three cached file 192 cachedMobFile1 = (CachedMobFile) mobFileCache.openFile(fs, file1Path, cacheConf); 193 assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize()); 194 CachedMobFile cachedMobFile2 = (CachedMobFile) mobFileCache.openFile(fs, file2Path, cacheConf); 195 assertEquals(EXPECTED_CACHE_SIZE_TWO, mobFileCache.getCacheSize()); 196 CachedMobFile cachedMobFile3 = (CachedMobFile) mobFileCache.openFile(fs, file3Path, cacheConf); 197 // Before the evict 198 // Evict the cache, should close the first file 1 199 assertEquals(EXPECTED_CACHE_SIZE_THREE, mobFileCache.getCacheSize()); 200 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile1.getReferenceCount()); 201 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile2.getReferenceCount()); 202 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile3.getReferenceCount()); 203 mobFileCache.evict(); 204 assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize()); 205 assertEquals(EXPECTED_REFERENCE_ONE, cachedMobFile1.getReferenceCount()); 206 assertEquals(EXPECTED_REFERENCE_ONE, cachedMobFile2.getReferenceCount()); 207 assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile3.getReferenceCount()); 208 } 209}