HBASE-12332 [mob] improve how we resolve mobfiles in reads (Jingcheng Du and Jiajia Li)

This commit is contained in:
Jonathan M Hsieh 2015-03-05 09:59:59 -08:00
parent 2124d3df70
commit 45711ebaaf
2 changed files with 53 additions and 58 deletions

View File

@ -23,8 +23,10 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.NavigableSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
@ -58,6 +60,7 @@ import org.apache.hadoop.hbase.regionserver.compactions.CompactionContext;
import org.apache.hadoop.hbase.regionserver.compactions.CompactionThroughputController;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.HFileArchiveUtil;
import org.apache.hadoop.hbase.util.IdLock;
/**
* The store implementation to save MOBs (medium objects), it extends the HStore.
@ -90,10 +93,11 @@ public class HMobStore extends HStore {
private volatile long mobFlushedCellsSize = 0;
private volatile long mobScanCellsCount = 0;
private volatile long mobScanCellsSize = 0;
private List<Path> mobDirLocations;
private HColumnDescriptor family;
private TableLockManager tableLockManager;
private TableName tableLockName;
private Map<String, List<Path>> map = new ConcurrentHashMap<String, List<Path>>();
private final IdLock keyLock = new IdLock();
public HMobStore(final HRegion region, final HColumnDescriptor family,
final Configuration confParam) throws IOException {
@ -103,11 +107,12 @@ public class HMobStore extends HStore {
this.homePath = MobUtils.getMobHome(conf);
this.mobFamilyPath = MobUtils.getMobFamilyPath(conf, this.getTableName(),
family.getNameAsString());
mobDirLocations = new ArrayList<Path>();
mobDirLocations.add(mobFamilyPath);
List<Path> locations = new ArrayList<Path>(2);
locations.add(mobFamilyPath);
TableName tn = region.getTableDesc().getTableName();
mobDirLocations.add(HFileArchiveUtil.getStoreArchivePath(conf, tn, MobUtils
.getMobRegionInfo(tn).getEncodedName(), family.getNameAsString()));
locations.add(HFileArchiveUtil.getStoreArchivePath(conf, tn, MobUtils.getMobRegionInfo(tn)
.getEncodedName(), family.getNameAsString()));
map.put(Bytes.toString(tn.getName()), locations);
if (region.getRegionServerServices() != null) {
tableLockManager = region.getRegionServerServices().getTableLockManager();
tableLockName = MobUtils.getTableLockName(getTableName());
@ -310,9 +315,28 @@ public class HMobStore extends HStore {
Cell result = null;
if (MobUtils.hasValidMobRefCellValue(reference)) {
String fileName = MobUtils.getMobFileName(reference);
result = readCell(mobDirLocations, fileName, reference, cacheBlocks);
if (result == null) {
result = readClonedCell(fileName, reference, cacheBlocks);
Tag tableNameTag = MobUtils.getTableNameTag(reference);
if (tableNameTag != null) {
byte[] tableName = tableNameTag.getValue();
String tableNameString = Bytes.toString(tableName);
List<Path> locations = map.get(tableNameString);
if (locations == null) {
IdLock.Entry lockEntry = keyLock.getLockEntry(tableNameString.hashCode());
try {
locations = map.get(tableNameString);
if (locations == null) {
locations = new ArrayList<Path>(2);
TableName tn = TableName.valueOf(tableName);
locations.add(MobUtils.getMobFamilyPath(conf, tn, family.getNameAsString()));
locations.add(HFileArchiveUtil.getStoreArchivePath(conf, tn, MobUtils
.getMobRegionInfo(tn).getEncodedName(), family.getNameAsString()));
map.put(tableNameString, locations);
}
} finally {
keyLock.releaseLockEntry(lockEntry);
}
}
result = readCell(locations, fileName, reference, cacheBlocks);
}
}
if (result == null) {
@ -353,11 +377,18 @@ public class HMobStore extends HStore {
return file.readCell(search, cacheMobBlocks);
} catch (IOException e) {
mobCacheConfig.getMobFileCache().evictFile(fileName);
if (e instanceof FileNotFoundException) {
if ((e instanceof FileNotFoundException) ||
(e.getCause() instanceof FileNotFoundException)) {
LOG.warn("Fail to read the cell, the mob file " + path + " doesn't exist", e);
} else {
throw e;
}
} catch (NullPointerException e) {
mobCacheConfig.getMobFileCache().evictFile(fileName);
LOG.warn("Fail to read the cell", e);
} catch (AssertionError e) {
mobCacheConfig.getMobFileCache().evictFile(fileName);
LOG.warn("Fail to read the cell", e);
} finally {
if (file != null) {
mobCacheConfig.getMobFileCache().closeFile(file);
@ -365,43 +396,10 @@ public class HMobStore extends HStore {
}
}
LOG.error("The mob file " + fileName + " could not be found in the locations "
+ mobDirLocations);
+ locations);
return null;
}
/**
* Reads the cell from a mob file of source table.
* The table might be cloned, in this case only hfile link is created in the new table,
* and the mob file is located in the source table directories.
* 1. The working directory of the source table.
* 2. The archive directory of the source table.
* Reads the cell from the files located in both of the above directories.
* @param fileName The file to be read.
* @param search The cell to be searched.
* @param cacheMobBlocks Whether the scanner should cache blocks.
* @return The found cell. Null if there's no such a cell.
* @throws IOException
*/
private Cell readClonedCell(String fileName, Cell search, boolean cacheMobBlocks)
throws IOException {
Tag tableNameTag = MobUtils.getTableNameTag(search);
if (tableNameTag == null) {
return null;
}
byte[] tableName = tableNameTag.getValue();
if (Bytes.equals(this.getTableName().getName(), tableName)) {
return null;
}
// the possible locations in the source table.
List<Path> locations = new ArrayList<Path>();
TableName tn = TableName.valueOf(tableName);
locations.add(MobUtils.getMobFamilyPath(conf, tn, family.getNameAsString()));
locations.add(HFileArchiveUtil.getStoreArchivePath(conf, tn, MobUtils.getMobRegionInfo(tn)
.getEncodedName(), family.getNameAsString()));
// read the cell from the source table.
return readCell(locations, fileName, search, cacheMobBlocks);
}
/**
* Gets the mob file path.
* @return The mob file path.

View File

@ -42,6 +42,8 @@ import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.Tag;
import org.apache.hadoop.hbase.TagType;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.mob.MobConstants;
@ -164,8 +166,8 @@ public class TestHMobStore {
KeyValue key3 = new KeyValue(row2, family, qf3, 1, value2);
KeyValue[] keys = new KeyValue[] { key1, key2, key3 };
int maxKeyCount = keys.length;
StoreFile.Writer mobWriter = store.createWriterInTmp(currentDate,
maxKeyCount, hcd.getCompactionCompression(), region.getStartKey());
StoreFile.Writer mobWriter = store.createWriterInTmp(currentDate, maxKeyCount,
hcd.getCompactionCompression(), region.getStartKey());
mobFilePath = mobWriter.getPath();
mobWriter.append(key1);
@ -173,20 +175,15 @@ public class TestHMobStore {
mobWriter.append(key3);
mobWriter.close();
int valueLength1 = key1.getValueLength();
int valueLength2 = key2.getValueLength();
int valueLength3 = key3.getValueLength();
String targetPathName = MobUtils.formatDate(currentDate);
byte[] referenceValue =
Bytes.toBytes(targetPathName + Path.SEPARATOR
+ mobFilePath.getName());
byte[] newReferenceValue1 = Bytes.add(Bytes.toBytes(valueLength1), referenceValue);
byte[] newReferenceValue2 = Bytes.add(Bytes.toBytes(valueLength2), referenceValue);
byte[] newReferenceValue3 = Bytes.add(Bytes.toBytes(valueLength3), referenceValue);
seekKey1 = new KeyValue(row, family, qf1, Long.MAX_VALUE, newReferenceValue1);
seekKey2 = new KeyValue(row, family, qf2, Long.MAX_VALUE, newReferenceValue2);
seekKey3 = new KeyValue(row2, family, qf3, Long.MAX_VALUE, newReferenceValue3);
byte[] referenceValue = Bytes.toBytes(targetPathName + Path.SEPARATOR + mobFilePath.getName());
Tag tableNameTag = new Tag(TagType.MOB_TABLE_NAME_TAG_TYPE, store.getTableName().getName());
KeyValue kv1 = new KeyValue(row, family, qf1, Long.MAX_VALUE, referenceValue);
KeyValue kv2 = new KeyValue(row, family, qf2, Long.MAX_VALUE, referenceValue);
KeyValue kv3 = new KeyValue(row2, family, qf3, Long.MAX_VALUE, referenceValue);
seekKey1 = MobUtils.createMobRefKeyValue(kv1, referenceValue, tableNameTag);
seekKey2 = MobUtils.createMobRefKeyValue(kv2, referenceValue, tableNameTag);
seekKey3 = MobUtils.createMobRefKeyValue(kv3, referenceValue, tableNameTag);
}
/**