Skip to content

Commit

Permalink
HBASE-12332 [mob] improve how we resolve mobfiles in reads (Jingcheng…
Browse files Browse the repository at this point in the history
… Du and Jiajia Li)
  • Loading branch information
jmhsieh committed Mar 5, 2015
1 parent 2124d3d commit 45711eb
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 58 deletions.
Expand Up @@ -23,8 +23,10 @@
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;
Expand Down Expand Up @@ -58,6 +60,7 @@
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.
Expand Down Expand Up @@ -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 {
Expand All @@ -103,11 +107,12 @@ public HMobStore(final HRegion region, final HColumnDescriptor family,
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());
Expand Down Expand Up @@ -310,9 +315,28 @@ public Cell resolve(Cell reference, boolean cacheBlocks) throws IOException {
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) {
Expand Down Expand Up @@ -353,55 +377,29 @@ private Cell readCell(List<Path> locations, String fileName, Cell search, boolea
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);
}
}
}
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.
Expand Down
Expand Up @@ -42,6 +42,8 @@
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;
Expand Down Expand Up @@ -164,29 +166,24 @@ private void init(Configuration conf, HColumnDescriptor hcd)
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);
mobWriter.append(key2);
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);
}

/**
Expand Down

0 comments on commit 45711eb

Please sign in to comment.