|
43 | 43 | import org.apache.hadoop.hbase.client.RegionInfo; |
44 | 44 | import org.apache.hadoop.hbase.client.RegionInfoBuilder; |
45 | 45 | import org.apache.hadoop.hbase.client.Table; |
| 46 | +import org.apache.hadoop.hbase.client.TableDescriptor; |
| 47 | +import org.apache.hadoop.hbase.client.TableDescriptorBuilder; |
46 | 48 | import org.apache.hadoop.hbase.fs.HFileSystem; |
47 | 49 | import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTracker; |
48 | 50 | import org.apache.hadoop.hbase.regionserver.storefiletracker.StoreFileTrackerFactory; |
|
51 | 53 | import org.apache.hadoop.hbase.util.Bytes; |
52 | 54 | import org.apache.hadoop.hbase.util.CommonFSUtils; |
53 | 55 | import org.apache.hadoop.hbase.util.FSUtils; |
| 56 | +import org.apache.hadoop.hbase.wal.WAL; |
54 | 57 | import org.apache.hadoop.util.Progressable; |
55 | 58 | import org.junit.ClassRule; |
56 | 59 | import org.junit.Rule; |
@@ -387,4 +390,78 @@ public void testTempAndCommit() throws IOException { |
387 | 390 |
|
388 | 391 | fs.delete(rootDir, true); |
389 | 392 | } |
| 393 | + |
| 394 | + /** |
| 395 | + * Test for HBASE-29662: HRegion.initialize() should fail when trying to recreate .regioninfo file |
| 396 | + * after the region directory has been deleted. This validates that .regioninfo file creation does |
| 397 | + * not create parent directories recursively. |
| 398 | + */ |
| 399 | + @Test |
| 400 | + public void testHRegionInitializeFailsWithDeletedRegionDir() throws Exception { |
| 401 | + LOG.info("Testing HRegion initialize failure with deleted region directory"); |
| 402 | + |
| 403 | + TEST_UTIL = new HBaseTestingUtil(); |
| 404 | + Configuration conf = TEST_UTIL.getConfiguration(); |
| 405 | + Path testDir = TEST_UTIL.getDataTestDir("testHRegionInitFailure"); |
| 406 | + FileSystem fs = testDir.getFileSystem(conf); |
| 407 | + |
| 408 | + // Create table descriptor |
| 409 | + TableName tableName = TableName.valueOf("TestHRegionInitWithDeletedDir"); |
| 410 | + byte[] family = Bytes.toBytes("info"); |
| 411 | + TableDescriptor htd = TableDescriptorBuilder.newBuilder(tableName) |
| 412 | + .setColumnFamily(ColumnFamilyDescriptorBuilder.of(family)).build(); |
| 413 | + |
| 414 | + // Create region info |
| 415 | + RegionInfo regionInfo = |
| 416 | + RegionInfoBuilder.newBuilder(tableName).setStartKey(null).setEndKey(null).build(); |
| 417 | + |
| 418 | + Path tableDir = CommonFSUtils.getTableDir(testDir, tableName); |
| 419 | + |
| 420 | + // Create WAL for the region |
| 421 | + WAL wal = HBaseTestingUtil.createWal(conf, testDir, regionInfo); |
| 422 | + |
| 423 | + try { |
| 424 | + // Create region normally (this should succeed and create region directory) |
| 425 | + LOG.info("Creating region normally - should succeed"); |
| 426 | + HRegion region = HRegion.createHRegion(regionInfo, testDir, conf, htd, wal, true); |
| 427 | + |
| 428 | + // Verify region directory exists |
| 429 | + Path regionDir = new Path(tableDir, regionInfo.getEncodedName()); |
| 430 | + assertTrue("Region directory should exist after creation", fs.exists(regionDir)); |
| 431 | + |
| 432 | + Path regionInfoFile = new Path(regionDir, HRegionFileSystem.REGION_INFO_FILE); |
| 433 | + assertTrue("Region info file should exist after creation", fs.exists(regionInfoFile)); |
| 434 | + |
| 435 | + // Delete the region directory (simulating external deletion or corruption) |
| 436 | + assertTrue(fs.delete(regionDir, true)); |
| 437 | + assertFalse("Region directory should not exist after deletion", fs.exists(regionDir)); |
| 438 | + |
| 439 | + // Try to open/initialize the region again - this should fail |
| 440 | + LOG.info("Attempting to re-initialize region with deleted directory - should fail"); |
| 441 | + |
| 442 | + // Create a new region instance (simulating region server restart or reopen) |
| 443 | + HRegion newRegion = HRegion.newHRegion(tableDir, wal, fs, conf, regionInfo, htd, null); |
| 444 | + |
| 445 | + // Try to initialize - this should fail because the regionDir doesn't exist |
| 446 | + IOException exception = null; |
| 447 | + try { |
| 448 | + newRegion.initialize(null); |
| 449 | + } catch (IOException e) { |
| 450 | + exception = e; |
| 451 | + } |
| 452 | + |
| 453 | + // Verify the exception is related to missing parent directory |
| 454 | + assertNotNull("Exception should be thrown", exception); |
| 455 | + String exceptionMessage = exception.getMessage().toLowerCase(); |
| 456 | + assertTrue(exceptionMessage.contains("parent directory doesn't exist")); |
| 457 | + assertFalse("Region directory should still not exist after failed initialization", |
| 458 | + fs.exists(regionDir)); |
| 459 | + |
| 460 | + } finally { |
| 461 | + if (wal != null) { |
| 462 | + wal.close(); |
| 463 | + } |
| 464 | + TEST_UTIL.cleanupTestDir(); |
| 465 | + } |
| 466 | + } |
390 | 467 | } |
0 commit comments