blob: 8cfa0a68adb894a88abaada201a51a702edddf2c [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase.mob;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import java.util.Date;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
import org.apache.hadoop.hbase.client.RegionInfo;
import org.apache.hadoop.hbase.client.RegionInfoBuilder;
import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
import org.apache.hadoop.hbase.io.hfile.CacheConfig;
import org.apache.hadoop.hbase.regionserver.HMobStore;
import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.regionserver.StoreFileWriter;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
@Category(SmallTests.class)
public class TestMobFileCache {
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestMobFileCache.class);
private HBaseTestingUtility UTIL;
private HRegion region;
private Configuration conf;
private MobFileCache mobFileCache;
private Date currentDate = new Date();
private static final String TEST_CACHE_SIZE = "2";
private static final int EXPECTED_CACHE_SIZE_ZERO = 0;
private static final int EXPECTED_CACHE_SIZE_ONE = 1;
private static final int EXPECTED_CACHE_SIZE_TWO = 2;
private static final int EXPECTED_CACHE_SIZE_THREE = 3;
private static final long EXPECTED_REFERENCE_ONE = 1;
private static final long EXPECTED_REFERENCE_TWO = 2;
private static final String TABLE = "tableName";
private static final String FAMILY1 = "family1";
private static final String FAMILY2 = "family2";
private static final String FAMILY3 = "family3";
private static final byte[] ROW = Bytes.toBytes("row");
private static final byte[] ROW2 = Bytes.toBytes("row2");
private static final byte[] VALUE = Bytes.toBytes("value");
private static final byte[] VALUE2 = Bytes.toBytes("value2");
private static final byte[] QF1 = Bytes.toBytes("qf1");
private static final byte[] QF2 = Bytes.toBytes("qf2");
private static final byte[] QF3 = Bytes.toBytes("qf3");
@Before
public void setUp() throws Exception {
UTIL = new HBaseTestingUtility();
conf = UTIL.getConfiguration();
conf.set(MobConstants.MOB_FILE_CACHE_SIZE_KEY, TEST_CACHE_SIZE);
TableDescriptorBuilder tableDescriptorBuilder =
TableDescriptorBuilder.newBuilder(UTIL.createTableDescriptor(
TableName.valueOf("testMobFileCache"), ColumnFamilyDescriptorBuilder.DEFAULT_MIN_VERSIONS,
3, HConstants.FOREVER, ColumnFamilyDescriptorBuilder.DEFAULT_KEEP_DELETED));
ColumnFamilyDescriptor columnFamilyDescriptor =
ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(FAMILY1))
.setMobEnabled(true)
.setMobThreshold(0)
.build();
tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor);
columnFamilyDescriptor =
ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(FAMILY2))
.setMobEnabled(true)
.setMobThreshold(0)
.build();
tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor);
columnFamilyDescriptor =
ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(FAMILY3))
.setMobEnabled(true)
.setMobThreshold(0)
.build();
tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor);
TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
RegionInfo regionInfo = RegionInfoBuilder.newBuilder(tableDescriptor.getTableName()).build();
mobFileCache = new MobFileCache(conf);
region = HBaseTestingUtility
.createRegionAndWAL(regionInfo, UTIL.getDataTestDir(), conf, tableDescriptor, mobFileCache);
}
@After
public void tearDown() throws Exception {
region.close();
region.getFilesystem().delete(UTIL.getDataTestDir(), true);
}
/**
* Create the mob store file.
*/
private Path createMobStoreFile(String family) throws IOException {
return createMobStoreFile(HBaseConfiguration.create(), family);
}
/**
* Create the mob store file
*/
private Path createMobStoreFile(Configuration conf, String family) throws IOException {
ColumnFamilyDescriptor columnFamilyDescriptor =
ColumnFamilyDescriptorBuilder
.newBuilder(Bytes.toBytes(family))
.setMaxVersions(4)
.setMobEnabled(true).build();
return createMobStoreFile(columnFamilyDescriptor);
}
/**
* Create the mob store file
*/
private Path createMobStoreFile(ColumnFamilyDescriptor columnFamilyDescriptor)
throws IOException {
// Setting up a Store
TableName tn = TableName.valueOf(TABLE);
TableDescriptorBuilder tableDescriptorBuilder =
TableDescriptorBuilder.newBuilder(tn);
tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor);
HMobStore mobStore = (HMobStore) region.getStore(columnFamilyDescriptor.getName());
KeyValue key1 = new KeyValue(ROW, columnFamilyDescriptor.getName(), QF1, 1, VALUE);
KeyValue key2 = new KeyValue(ROW, columnFamilyDescriptor.getName(), QF2, 1, VALUE);
KeyValue key3 = new KeyValue(ROW2, columnFamilyDescriptor.getName(), QF3, 1, VALUE2);
KeyValue[] keys = new KeyValue[] { key1, key2, key3 };
int maxKeyCount = keys.length;
RegionInfo regionInfo = RegionInfoBuilder.newBuilder(tn).build();
StoreFileWriter mobWriter = mobStore.createWriterInTmp(currentDate,
maxKeyCount, columnFamilyDescriptor.getCompactionCompressionType(),
regionInfo.getStartKey(), false);
Path mobFilePath = mobWriter.getPath();
String fileName = mobFilePath.getName();
mobWriter.append(key1);
mobWriter.append(key2);
mobWriter.append(key3);
mobWriter.close();
String targetPathName = MobUtils.formatDate(currentDate);
Path targetPath = new Path(mobStore.getPath(), targetPathName);
mobStore.commitFile(mobFilePath, targetPath);
return new Path(targetPath, fileName);
}
@Test
public void testMobFileCache() throws Exception {
FileSystem fs = FileSystem.get(conf);
Path file1Path = createMobStoreFile(FAMILY1);
Path file2Path = createMobStoreFile(FAMILY2);
Path file3Path = createMobStoreFile(FAMILY3);
CacheConfig cacheConf = new CacheConfig(conf);
// Before open one file by the MobFileCache
assertEquals(EXPECTED_CACHE_SIZE_ZERO, mobFileCache.getCacheSize());
// Open one file by the MobFileCache
CachedMobFile cachedMobFile1 = (CachedMobFile) mobFileCache.openFile(
fs, file1Path, cacheConf);
assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize());
assertNotNull(cachedMobFile1);
assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile1.getReferenceCount());
// The evict is also managed by a schedule thread pool.
// And its check period is set as 3600 seconds by default.
// This evict should get the lock at the most time
mobFileCache.evict(); // Cache not full, evict it
assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize());
assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile1.getReferenceCount());
mobFileCache.evictFile(file1Path.getName()); // Evict one file
assertEquals(EXPECTED_CACHE_SIZE_ZERO, mobFileCache.getCacheSize());
assertEquals(EXPECTED_REFERENCE_ONE, cachedMobFile1.getReferenceCount());
cachedMobFile1.close(); // Close the cached mob file
// Reopen three cached file
cachedMobFile1 = (CachedMobFile) mobFileCache.openFile(
fs, file1Path, cacheConf);
assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize());
CachedMobFile cachedMobFile2 = (CachedMobFile) mobFileCache.openFile(
fs, file2Path, cacheConf);
assertEquals(EXPECTED_CACHE_SIZE_TWO, mobFileCache.getCacheSize());
CachedMobFile cachedMobFile3 = (CachedMobFile) mobFileCache.openFile(
fs, file3Path, cacheConf);
// Before the evict
// Evict the cache, should close the first file 1
assertEquals(EXPECTED_CACHE_SIZE_THREE, mobFileCache.getCacheSize());
assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile1.getReferenceCount());
assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile2.getReferenceCount());
assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile3.getReferenceCount());
mobFileCache.evict();
assertEquals(EXPECTED_CACHE_SIZE_ONE, mobFileCache.getCacheSize());
assertEquals(EXPECTED_REFERENCE_ONE, cachedMobFile1.getReferenceCount());
assertEquals(EXPECTED_REFERENCE_ONE, cachedMobFile2.getReferenceCount());
assertEquals(EXPECTED_REFERENCE_TWO, cachedMobFile3.getReferenceCount());
}
}