HBASE-13107 Refactor MOB Snapshot logic to reduce code duplication (Jingcheng Du)

This commit is contained in:
Jonathan M Hsieh 2015-03-05 11:29:21 -08:00
parent 0d6cac9b1e
commit dae8f236dc
2 changed files with 72 additions and 167 deletions

View File

@ -427,67 +427,7 @@ public class RestoreSnapshotHelper {
*/ */
private void restoreRegion(final HRegionInfo regionInfo, private void restoreRegion(final HRegionInfo regionInfo,
final SnapshotRegionManifest regionManifest) throws IOException { final SnapshotRegionManifest regionManifest) throws IOException {
Map<String, List<SnapshotRegionManifest.StoreFile>> snapshotFiles = restoreRegion(regionInfo, regionManifest, new Path(tableDir, regionInfo.getEncodedName()));
getRegionHFileReferences(regionManifest);
Path regionDir = new Path(tableDir, regionInfo.getEncodedName());
String tableName = tableDesc.getTableName().getNameAsString();
// Restore families present in the table
for (Path familyDir: FSUtils.getFamilyDirs(fs, regionDir)) {
byte[] family = Bytes.toBytes(familyDir.getName());
Set<String> familyFiles = getTableRegionFamilyFiles(familyDir);
List<SnapshotRegionManifest.StoreFile> snapshotFamilyFiles =
snapshotFiles.remove(familyDir.getName());
if (snapshotFamilyFiles != null) {
List<SnapshotRegionManifest.StoreFile> hfilesToAdd =
new ArrayList<SnapshotRegionManifest.StoreFile>();
for (SnapshotRegionManifest.StoreFile storeFile: snapshotFamilyFiles) {
if (familyFiles.contains(storeFile.getName())) {
// HFile already present
familyFiles.remove(storeFile.getName());
} else {
// HFile missing
hfilesToAdd.add(storeFile);
}
}
// Remove hfiles not present in the snapshot
for (String hfileName: familyFiles) {
Path hfile = new Path(familyDir, hfileName);
LOG.trace("Removing hfile=" + hfileName +
" from region=" + regionInfo.getEncodedName() + " table=" + tableName);
HFileArchiver.archiveStoreFile(conf, fs, regionInfo, tableDir, family, hfile);
}
// Restore Missing files
for (SnapshotRegionManifest.StoreFile storeFile: hfilesToAdd) {
LOG.debug("Adding HFileLink " + storeFile.getName() +
" to region=" + regionInfo.getEncodedName() + " table=" + tableName);
restoreStoreFile(familyDir, regionInfo, storeFile);
}
} else {
// Family doesn't exists in the snapshot
LOG.trace("Removing family=" + Bytes.toString(family) +
" from region=" + regionInfo.getEncodedName() + " table=" + tableName);
HFileArchiver.archiveFamily(fs, conf, regionInfo, tableDir, family);
fs.delete(familyDir, true);
}
}
// Add families not present in the table
for (Map.Entry<String, List<SnapshotRegionManifest.StoreFile>> familyEntry:
snapshotFiles.entrySet()) {
Path familyDir = new Path(regionDir, familyEntry.getKey());
if (!fs.mkdirs(familyDir)) {
throw new IOException("Unable to create familyDir=" + familyDir);
}
for (SnapshotRegionManifest.StoreFile storeFile: familyEntry.getValue()) {
LOG.trace("Adding HFileLink " + storeFile.getName() + " to table=" + tableName);
restoreStoreFile(familyDir, regionInfo, storeFile);
}
}
} }
/** /**
@ -499,10 +439,19 @@ public class RestoreSnapshotHelper {
if (regionManifest == null) { if (regionManifest == null) {
return; return;
} }
restoreRegion(regionInfo, regionManifest,
MobUtils.getMobRegionPath(conf, tableDesc.getTableName()));
}
/**
* Restore region by removing files not in the snapshot
* and adding the missing ones from the snapshot.
*/
private void restoreRegion(final HRegionInfo regionInfo,
final SnapshotRegionManifest regionManifest, Path regionDir) throws IOException {
Map<String, List<SnapshotRegionManifest.StoreFile>> snapshotFiles = Map<String, List<SnapshotRegionManifest.StoreFile>> snapshotFiles =
getRegionHFileReferences(regionManifest); getRegionHFileReferences(regionManifest);
Path regionDir = MobUtils.getMobRegionPath(conf, tableDesc.getTableName());
String tableName = tableDesc.getTableName().getNameAsString(); String tableName = tableDesc.getTableName().getNameAsString();
// Restore families present in the table // Restore families present in the table
@ -668,15 +617,8 @@ public class RestoreSnapshotHelper {
*/ */
private void cloneRegion(final HRegion region, final HRegionInfo snapshotRegionInfo, private void cloneRegion(final HRegion region, final HRegionInfo snapshotRegionInfo,
final SnapshotRegionManifest manifest) throws IOException { final SnapshotRegionManifest manifest) throws IOException {
final Path regionDir = new Path(tableDir, region.getRegionInfo().getEncodedName()); cloneRegion(new Path(tableDir, region.getRegionInfo().getEncodedName()), snapshotRegionInfo,
final String tableName = tableDesc.getTableName().getNameAsString(); manifest);
for (SnapshotRegionManifest.FamilyFiles familyFiles: manifest.getFamilyFilesList()) {
Path familyDir = new Path(regionDir, familyFiles.getFamilyName().toStringUtf8());
for (SnapshotRegionManifest.StoreFile storeFile: familyFiles.getStoreFilesList()) {
LOG.info("Adding HFileLink " + storeFile.getName() + " to table=" + tableName);
restoreStoreFile(familyDir, snapshotRegionInfo, storeFile);
}
}
} }
/** /**

View File

@ -38,12 +38,10 @@ import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableDescriptor; import org.apache.hadoop.hbase.TableDescriptor;
import org.apache.hadoop.hbase.errorhandling.ForeignExceptionSnare; import org.apache.hadoop.hbase.errorhandling.ForeignExceptionSnare;
import org.apache.hadoop.hbase.mob.MobConstants;
import org.apache.hadoop.hbase.mob.MobUtils; import org.apache.hadoop.hbase.mob.MobUtils;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription; import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
@ -171,39 +169,42 @@ public class SnapshotManifest {
Path mobRegionPath = MobUtils.getMobRegionPath(conf, regionInfo.getTable()); Path mobRegionPath = MobUtils.getMobRegionPath(conf, regionInfo.getTable());
for (HColumnDescriptor hcd : hcds) { for (HColumnDescriptor hcd : hcds) {
// 2.1. build the snapshot reference for the store if it's a mob store // 2.1. build the snapshot reference for the store if it's a mob store
if (hcd.isMobEnabled()) { if (!hcd.isMobEnabled()) {
continue;
}
Object familyData = visitor.familyOpen(regionData, hcd.getName()); Object familyData = visitor.familyOpen(regionData, hcd.getName());
monitor.rethrowException(); monitor.rethrowException();
Path storePath = MobUtils.getMobFamilyPath(mobRegionPath, hcd.getNameAsString()); Path storePath = MobUtils.getMobFamilyPath(mobRegionPath, hcd.getNameAsString());
try { if (!fs.exists(storePath)) {
if (fs.exists(storePath)) { continue;
}
FileStatus[] stats = fs.listStatus(storePath); FileStatus[] stats = fs.listStatus(storePath);
if (stats == null) {
continue;
}
List<StoreFileInfo> storeFiles = new ArrayList<StoreFileInfo>();
for (FileStatus stat : stats) {
storeFiles.add(new StoreFileInfo(conf, fs, stat));
}
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("Adding snapshot references for " + stats.length + " hfiles"); LOG.debug("Adding snapshot references for " + storeFiles + " hfiles");
} }
// 2.2. iterate through all the mob files and create "references". // 2.2. iterate through all the mob files and create "references".
for (int i = 0, fz = stats.length; i < fz; i++) { for (int i = 0, sz = storeFiles.size(); i < sz; i++) {
FileStatus stat = stats[i]; StoreFileInfo storeFile = storeFiles.get(i);
monitor.rethrowException(); monitor.rethrowException();
// create "reference" to this store file. // create "reference" to this store file.
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("Adding reference for file (" + (i + 1) + "/" + fz + "): " LOG.debug("Adding reference for file (" + (i + 1) + "/" + sz + "): "
+ stat.getPath()); + storeFile.getPath());
} }
StoreFileInfo mobStoreFileInfo = new StoreFileInfo(conf, fs, stat); visitor.storeFile(regionData, familyData, storeFile);
visitor.storeFile(regionData, familyData, mobStoreFileInfo);
}
}
} catch (FileNotFoundException e) {
// do nothing
} }
visitor.familyClose(regionData, familyData); visitor.familyClose(regionData, familyData);
} }
}
visitor.regionClose(regionData); visitor.regionClose(regionData);
} }
@ -255,70 +256,8 @@ public class SnapshotManifest {
// 0. Get the ManifestBuilder/RegionVisitor // 0. Get the ManifestBuilder/RegionVisitor
RegionVisitor visitor = createRegionVisitor(desc); RegionVisitor visitor = createRegionVisitor(desc);
HRegionInfo mobRegionInfo = new HRegionInfo(regionInfo.getTable(), boolean isMobRegion = MobUtils.isMobRegionInfo(regionInfo);
MobConstants.MOB_REGION_NAME_BYTES, HConstants.EMPTY_END_ROW, false, 0);
if (mobRegionInfo.getEncodedName().equals(regionInfo.getEncodedName())) {
// this is a mob region
try { try {
HRegionFileSystem mobRegionFs = HRegionFileSystem.openRegionFromFileSystem(conf, fs,
tableDir, regionInfo, true);
monitor.rethrowException();
// 1. dump region meta info into the snapshot directory
LOG.debug("Storing region-info for snapshot.");
Object regionData = visitor.regionOpen(regionInfo);
monitor.rethrowException();
// 2. iterate through all the stores in the region
LOG.debug("Creating references for hfiles");
// This ensures that we have an atomic view of the directory as long as we have < ls limit
// (batch size of the files in a directory) on the namenode. Otherwise, we get back the
// files in batches and may miss files being added/deleted. This could be more robust
// (iteratively
// checking to see if we have all the files until we are sure), but the limit is currently
// 1000 files/batch, far more than the number of store files under a single column family.
Collection<String> familyNames = mobRegionFs.getFamilies();
if (familyNames != null) {
Path regionPath = MobUtils.getMobRegionPath(conf, regionInfo.getTable());
for (String familyName: familyNames) {
Object familyData = visitor.familyOpen(regionData, Bytes.toBytes(familyName));
monitor.rethrowException();
Path storePath = MobUtils.getMobFamilyPath(regionPath, familyName);
try {
if (fs.exists(storePath)) {
FileStatus[] stats = fs.listStatus(storePath);
if (LOG.isDebugEnabled()) {
LOG.debug("Adding snapshot references for " + stats.length + " hfiles");
}
// 2.2. iterate through all the mob files and create "references".
for (int i = 0, fz = stats.length; i < fz; i++) {
FileStatus stat = stats[i];
monitor.rethrowException();
// create "reference" to this store file.
if (LOG.isDebugEnabled()) {
LOG.debug("Adding reference for file (" + (i + 1) + "/" + fz + "): "
+ stat.getPath());
}
StoreFileInfo mobStoreFileInfo = new StoreFileInfo(conf, fs, stat);
visitor.storeFile(regionData, familyData, mobStoreFileInfo);
}
}
} catch (FileNotFoundException e) {
// do nothing
}
visitor.familyClose(regionData, familyData);
}
}
visitor.regionClose(regionData);
} catch(IOException e) {
//the mob directory might not be created yet, so do nothing here
}
} else {
// Open the RegionFS // Open the RegionFS
HRegionFileSystem regionFs = HRegionFileSystem.openRegionFromFileSystem(conf, fs, HRegionFileSystem regionFs = HRegionFileSystem.openRegionFromFileSystem(conf, fs,
tableDir, regionInfo, true); tableDir, regionInfo, true);
@ -343,9 +282,28 @@ public class SnapshotManifest {
Object familyData = visitor.familyOpen(regionData, Bytes.toBytes(familyName)); Object familyData = visitor.familyOpen(regionData, Bytes.toBytes(familyName));
monitor.rethrowException(); monitor.rethrowException();
Collection<StoreFileInfo> storeFiles = regionFs.getStoreFiles(familyName); Collection<StoreFileInfo> storeFiles = null;
if (isMobRegion) {
Path regionPath = MobUtils.getMobRegionPath(conf, regionInfo.getTable());
Path storePath = MobUtils.getMobFamilyPath(regionPath, familyName);
if (!fs.exists(storePath)) {
continue;
}
FileStatus[] stats = fs.listStatus(storePath);
if (stats == null) {
continue;
}
storeFiles = new ArrayList<StoreFileInfo>();
for (FileStatus stat : stats) {
storeFiles.add(new StoreFileInfo(conf, fs, stat));
}
} else {
storeFiles = regionFs.getStoreFiles(familyName);
}
if (storeFiles == null) { if (storeFiles == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("No files under family: " + familyName); LOG.debug("No files under family: " + familyName);
}
continue; continue;
} }
@ -369,6 +327,11 @@ public class SnapshotManifest {
} }
} }
visitor.regionClose(regionData); visitor.regionClose(regionData);
} catch (IOException e) {
// the mob directory might not be created yet, so do nothing when it is a mob region
if (!isMobRegion) {
throw e;
}
} }
} }