diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HMobStore.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HMobStore.java index 569ad06..f221324 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HMobStore.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HMobStore.java @@ -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; @@ -89,8 +91,8 @@ private volatile long mobFlushedCellsSize = 0; private volatile long mobScanCellsCount = 0; private volatile long mobScanCellsSize = 0; - private List mobDirLocations; private HColumnDescriptor family; + private Map> map = new ConcurrentHashMap>(); public HMobStore(final HRegion region, final HColumnDescriptor family, final Configuration confParam) throws IOException { @@ -100,11 +102,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(); - mobDirLocations.add(mobFamilyPath); + List locations = new ArrayList(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); } /** @@ -266,9 +269,25 @@ 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 locations = map.get(tableNameString); + if (locations == null) { + synchronized (map) { + locations = map.get(tableNameString); + if (locations == null) { + locations = new ArrayList(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); + } + } + } + result = readCell(locations, fileName, reference, cacheBlocks); } } if (result == null) { @@ -314,6 +333,12 @@ private Cell readCell(List locations, String fileName, Cell search, boolea } 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); @@ -321,44 +346,11 @@ private Cell readCell(List locations, String fileName, Cell search, boolea } } 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 locations = new ArrayList(); - 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. */ diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHMobStore.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHMobStore.java index 30b74d4..bfd9dbb 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHMobStore.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHMobStore.java @@ -42,6 +42,8 @@ import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.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; @@ -160,8 +162,8 @@ 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); @@ -169,20 +171,15 @@ private void init(Configuration conf, HColumnDescriptor hcd) 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); } /**