Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -638,26 +638,28 @@ private void cloneHdfsMobRegion(final Map<String, SnapshotRegionManifest> region
final RegionInfo region) throws IOException {
// clone region info (change embedded tableName with the new one)
Path clonedRegionPath = MobUtils.getMobRegionPath(rootDir, tableDesc.getTableName());
cloneRegion(MobUtils.getMobRegionInfo(tableDesc.getTableName()), clonedRegionPath, region,
regionManifests.get(region.getEncodedName()));
cloneRegularOrMobRegion(MobUtils.getMobRegionInfo(tableDesc.getTableName()), clonedRegionPath,
region, regionManifests.get(region.getEncodedName()));
}

/**
* Clone region directory content from the snapshot info. Each region is encoded with the table
* name, so the cloned region will have a different region name. Instead of copying the hfiles a
* HFileLink is created.
* Clone region directory content from a snapshot manifest. This method is used for both regular
* regions and MOB regions. Instead of copying the hfiles a HFileLink is created.
* @param regionDir {@link Path} cloned dir
*/
private void cloneRegion(final RegionInfo newRegionInfo, final Path regionDir,
private void cloneRegularOrMobRegion(final RegionInfo newRegionInfo, final Path regionDir,
final RegionInfo snapshotRegionInfo, final SnapshotRegionManifest manifest) throws IOException {
final String tableName = tableDesc.getTableName().getNameAsString();
final String snapshotName = snapshotDesc.getName();
final boolean isMobRegion = MobUtils.isMobRegionInfo(newRegionInfo);
final Path parentDir =
isMobRegion ? MobUtils.getMobTableDir(rootDir, tableDesc.getTableName()) : tableDir;
for (SnapshotRegionManifest.FamilyFiles familyFiles : manifest.getFamilyFilesList()) {
Path familyDir = new Path(regionDir, familyFiles.getFamilyName().toStringUtf8());
List<StoreFileInfo> clonedFiles = new ArrayList<>();
HRegionFileSystem regionFS = (fs.exists(regionDir))
? HRegionFileSystem.openRegionFromFileSystem(conf, fs, tableDir, newRegionInfo, false)
: HRegionFileSystem.createRegionOnFileSystem(conf, fs, tableDir, newRegionInfo);
HRegionFileSystem regionFS = fs.exists(regionDir)
? HRegionFileSystem.openRegionFromFileSystem(conf, fs, parentDir, newRegionInfo, false)
: HRegionFileSystem.createRegionOnFileSystem(conf, fs, parentDir, newRegionInfo);

Configuration sftConf = StoreUtils.createStoreConfiguration(conf, tableDesc,
tableDesc.getColumnFamily(familyFiles.getFamilyName().toByteArray()));
Expand All @@ -675,7 +677,7 @@ private void cloneRegion(final RegionInfo newRegionInfo, final Path regionDir,
for (SnapshotRegionManifest.StoreFile storeFile : familyFiles.getStoreFilesList()) {
LOG.info("Adding HFileLink " + storeFile.getName() + " from cloned region " + "in snapshot "
+ snapshotName + " to table=" + tableName);
if (MobUtils.isMobRegionInfo(newRegionInfo)) {
if (isMobRegion) {
String mobFileName =
HFileLink.createHFileLinkName(snapshotRegionInfo, storeFile.getName());
Path mobPath = new Path(familyDir, mobFileName);
Expand Down Expand Up @@ -704,8 +706,8 @@ private void cloneRegion(final RegionInfo newRegionInfo, final Path regionDir,
*/
private void cloneRegion(final HRegion region, final RegionInfo snapshotRegionInfo,
final SnapshotRegionManifest manifest) throws IOException {
cloneRegion(region.getRegionInfo(), new Path(tableDir, region.getRegionInfo().getEncodedName()),
snapshotRegionInfo, manifest);
cloneRegularOrMobRegion(region.getRegionInfo(),
new Path(tableDir, region.getRegionInfo().getEncodedName()), snapshotRegionInfo, manifest);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,24 @@
*/
package org.apache.hadoop.hbase.snapshot;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseTestingUtil;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.mob.MobConstants;
import org.apache.hadoop.hbase.mob.MobUtils;
import org.apache.hadoop.hbase.snapshot.MobSnapshotTestingUtils.SnapshotMock;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.CommonFSUtils;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -55,4 +64,47 @@ protected void createTableAndSnapshot(TableName tableName, String snapshotName)
TEST_UTIL.loadTable(table, column);
TEST_UTIL.getAdmin().snapshot(snapshotName, tableName);
}

@Test
public void testRestoreMobTableFromSnapshot() throws IOException {
TableName mobTableName = TableName.valueOf("testRestoreMobTable");
String snapshotName = "testRestoreMobTable_snapshot";
createTableAndSnapshot(mobTableName, snapshotName);
assertTrue(TEST_UTIL.getAdmin().tableExists(mobTableName));
assertTrue(MobUtils.hasMobColumns(TEST_UTIL.getAdmin().getDescriptor(mobTableName)));
assertTrue(TEST_UTIL.getAdmin().listSnapshots().stream()
.anyMatch(snapshotDescription -> snapshotName.equals(snapshotDescription.getName())));

// Clone the snapshot to a new MOB table
TableName newMobTableName = TableName.valueOf("newTestRestoreMobTable");
TEST_UTIL.getAdmin().cloneSnapshot(snapshotName, newMobTableName);
assertTrue(TEST_UTIL.getAdmin().tableExists(newMobTableName));
assertTrue(MobUtils.hasMobColumns(TEST_UTIL.getAdmin().getDescriptor(newMobTableName)));

Path hbaseRootDir = TEST_UTIL.getDefaultRootDirPath();
Path mobRegionPath = MobUtils.getMobTableDir(hbaseRootDir, newMobTableName);
assertTrue(fs.exists(mobRegionPath));
Path errorMobRegionPathInTableDir =
new Path(CommonFSUtils.getTableDir(hbaseRootDir, newMobTableName),
MobUtils.getMobRegionInfo(newMobTableName).getEncodedName());
assertFalse(fs.exists(errorMobRegionPathInTableDir));

try (Table originMobTable = TEST_UTIL.getConnection().getTable(mobTableName);
Table clonedMobTable = TEST_UTIL.getConnection().getTable(newMobTableName)) {
assertEquals(HBaseTestingUtil.countRows(originMobTable),
HBaseTestingUtil.countRows(clonedMobTable));
}

// Delete the original MOB table and restore it from the snapshot
TEST_UTIL.deleteTable(mobTableName);
assertFalse(TEST_UTIL.getAdmin().tableExists(mobTableName));
TEST_UTIL.getAdmin().cloneSnapshot(snapshotName, mobTableName);
assertTrue(TEST_UTIL.getAdmin().tableExists(mobTableName));
assertTrue(MobUtils.hasMobColumns(TEST_UTIL.getAdmin().getDescriptor(mobTableName)));
mobRegionPath = MobUtils.getMobTableDir(hbaseRootDir, mobTableName);
assertTrue(fs.exists(mobRegionPath));
errorMobRegionPathInTableDir = new Path(CommonFSUtils.getTableDir(hbaseRootDir, mobTableName),
MobUtils.getMobRegionInfo(mobTableName).getEncodedName());
assertFalse(fs.exists(errorMobRegionPathInTableDir));
}
}