You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by lu...@apache.org on 2026/08/24 15:57:52 UTC
(hbase) branch master updated: HBASE-30336 An extra empty MOB region dir is created under the table dir when restoring a MOB table from snapshot (#8558)
This is an automated email from the ASF dual-hosted git repository.
guluo2016 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/master by this push:
new 5d6b024a5ed HBASE-30336 An extra empty MOB region dir is created under the table dir when restoring a MOB table from snapshot (#8558)
5d6b024a5ed is described below
commit 5d6b024a5ed5d9b2f831e9e2808c91feac2c039c
Author: Peng Lu <lu...@apache.org>
AuthorDate: Mon Aug 24 23:57:45 2026 +0800
HBASE-30336 An extra empty MOB region dir is created under the table dir when restoring a MOB table from snapshot (#8558)
Signed-off-by: Xiao Liu <li...@apache.org>
---
.../hbase/snapshot/RestoreSnapshotHelper.java | 26 ++++++-----
.../snapshot/TestMobRestoreSnapshotHelper.java | 52 ++++++++++++++++++++++
2 files changed, 66 insertions(+), 12 deletions(-)
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java
index f0f1ba3899a..6b40601d154 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/RestoreSnapshotHelper.java
@@ -638,26 +638,28 @@ public class RestoreSnapshotHelper {
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()));
@@ -675,7 +677,7 @@ public class RestoreSnapshotHelper {
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);
@@ -704,8 +706,8 @@ public class RestoreSnapshotHelper {
*/
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);
}
/**
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/snapshot/TestMobRestoreSnapshotHelper.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/snapshot/TestMobRestoreSnapshotHelper.java
index 380044b733f..be26448bf9b 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/snapshot/TestMobRestoreSnapshotHelper.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/snapshot/TestMobRestoreSnapshotHelper.java
@@ -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;
@@ -55,4 +64,47 @@ public class TestMobRestoreSnapshotHelper extends TestRestoreSnapshotHelper {
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));
+ }
}