From 2739bd3592a2d2a89dbbc5227677dab58515485c Mon Sep 17 00:00:00 2001 From: liuxiaocs7 Date: Tue, 8 Sep 2026 13:15:05 +0800 Subject: [PATCH 1/4] HBASE-30368 TableSnapshotScanner fails on an already restored MOB table snapshot --- .../hbase/client/TableSnapshotScanner.java | 6 +++++ .../client/TestTableSnapshotScanner.java | 26 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java index 41bd0bd988bc..03a7e918cb6b 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java @@ -26,6 +26,7 @@ import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.PrivateCellUtil; import org.apache.hadoop.hbase.client.metrics.ScanMetrics; +import org.apache.hadoop.hbase.mob.MobUtils; import org.apache.hadoop.hbase.regionserver.MemStoreLAB; import org.apache.hadoop.hbase.snapshot.RestoreSnapshotHelper; import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils; @@ -160,6 +161,11 @@ private boolean isValidRegion(RegionInfo hri) { if (hri.isOffline() && (hri.isSplit() || hri.isSplitParent())) { return false; } + // The mob region is a dummy region used only to organise mob files under mobdir. It has no + // region directory under the table dir to open, and holds no rows. See HBASE-30365. + if (MobUtils.isMobRegionInfo(hri)) { + return false; + } return PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(), hri.getStartKey(), hri.getEndKey()); } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestTableSnapshotScanner.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestTableSnapshotScanner.java index 4b835719ecef..09663c910370 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestTableSnapshotScanner.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestTableSnapshotScanner.java @@ -49,6 +49,7 @@ import org.apache.hadoop.hbase.regionserver.StoreContext; import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTracker; import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory; +import org.apache.hadoop.hbase.snapshot.MobSnapshotTestingUtils; import org.apache.hadoop.hbase.snapshot.RestoreSnapshotHelper; import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils; import org.apache.hadoop.hbase.testclassification.ClientTests; @@ -370,6 +371,31 @@ public void testScannerWithRestoreScanner() throws Exception { } } + @Test + public void testScannerWithRestoredMobSnapshot() throws Exception { + TableName tableName = TableName.valueOf(methodName); + String snapshotName = methodName + "Snapshot"; + Path restoreDir = UTIL.getDataTestDirOnTestFS(snapshotName); + try { + MobSnapshotTestingUtils.createMobTable(UTIL, tableName, new byte[0][], 1, FAMILIES); + try (Table table = UTIL.getConnection().getTable(tableName)) { + UTIL.loadTable(table, FAMILIES); + } + UTIL.getAdmin().snapshot(snapshotName, tableName); + + Configuration conf = UTIL.getConfiguration(); + RestoreSnapshotHelper.copySnapshotForScanner(conf, fs, rootDir, restoreDir, snapshotName); + try (TableSnapshotScanner scanner = new TableSnapshotScanner(conf, rootDir, restoreDir, + snapshotName, new Scan().withStartRow(Bytes.toBytes("zzzz")), true)) { + assertNull(scanner.next()); + } + } finally { + fs.delete(restoreDir, true); + UTIL.getAdmin().deleteSnapshot(snapshotName); + UTIL.deleteTable(tableName); + } + } + private void testScanner(HBaseTestingUtil util, String snapshotName, int numRegions, boolean shutdownCluster) throws Exception { TableName tableName = TableName.valueOf("testScanner"); From f83615fea13070ce3e5a1174ac7b78f80bea0962 Mon Sep 17 00:00:00 2001 From: liuxiaocs7 Date: Tue, 8 Sep 2026 19:46:24 +0800 Subject: [PATCH 2/4] HBASE-30368 Clarify MOB pseudo-region issue references --- .../org/apache/hadoop/hbase/client/TableSnapshotScanner.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java index 03a7e918cb6b..39ba58e7b7ae 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java @@ -162,7 +162,8 @@ private boolean isValidRegion(RegionInfo hri) { return false; } // The mob region is a dummy region used only to organise mob files under mobdir. It has no - // region directory under the table dir to open, and holds no rows. See HBASE-30365. + // region directory under the table dir to open, and holds no rows. See HBASE-30365 and + // HBASE-30368. if (MobUtils.isMobRegionInfo(hri)) { return false; } From 0a31eb91c85588a51e49671a7f922d9272bb90e7 Mon Sep 17 00:00:00 2001 From: liuxiaocs7 Date: Wed, 9 Sep 2026 04:15:43 +0800 Subject: [PATCH 3/4] address comments --- .../hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.java | 2 +- .../org/apache/hadoop/hbase/client/TableSnapshotScanner.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.java b/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.java index e44d003cf5b6..b638c8854974 100644 --- a/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.java +++ b/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.java @@ -363,7 +363,7 @@ public static List getRegionInfosFromManifest(SnapshotManifest manif continue; } // The mob region is a dummy region used only to organise mob files under mobdir. It has no - // region directory under the table dir to open, and holds no rows. See HBASE-30365. + // region directory under the table dir to open. See HBASE-30365 and HBASE-30368. if (MobUtils.isMobRegionInfo(hri)) { continue; } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java index 39ba58e7b7ae..7e17d6303fdc 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/TableSnapshotScanner.java @@ -162,8 +162,7 @@ private boolean isValidRegion(RegionInfo hri) { return false; } // The mob region is a dummy region used only to organise mob files under mobdir. It has no - // region directory under the table dir to open, and holds no rows. See HBASE-30365 and - // HBASE-30368. + // region directory under the table dir to open. See HBASE-30365 and HBASE-30368. if (MobUtils.isMobRegionInfo(hri)) { return false; } From 56ac75c4b62e84b0336255859c505418add9839c Mon Sep 17 00:00:00 2001 From: liuxiaocs7 Date: Wed, 9 Sep 2026 04:50:57 +0800 Subject: [PATCH 4/4] update --- .../hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.java b/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.java index b638c8854974..405dd4d94257 100644 --- a/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.java +++ b/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.java @@ -363,7 +363,7 @@ public static List getRegionInfosFromManifest(SnapshotManifest manif continue; } // The mob region is a dummy region used only to organise mob files under mobdir. It has no - // region directory under the table dir to open. See HBASE-30365 and HBASE-30368. + // region directory under the table dir to open. See HBASE-30365. if (MobUtils.isMobRegionInfo(hri)) { continue; }