From 4d091166951a0b53e5fdd9dc694b4e5a12dc527c Mon Sep 17 00:00:00 2001 From: tedyu Date: Tue, 11 Oct 2016 07:19:54 -0700 Subject: [PATCH] HBASE-16716 OfflineMetaRepair leaves empty directory inside /hbase/WALs which remains forever (Pankaj Kumar) --- .../apache/hadoop/hbase/util/HBaseFsck.java | 33 +++++++++++++++---- .../util/hbck/TestOfflineMetaRebuildBase.java | 25 ++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java index efd75a63d1b..a31b7d1b85a 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/util/HBaseFsck.java @@ -1388,10 +1388,11 @@ public class HBaseFsck extends Configured implements Closeable { /** * This borrows code from MasterFileSystem.bootstrap(). Explicitly creates it's own WAL, so be * sure to close it as well as the region when you're finished. - * + * @param walFactoryID A unique identifier for WAL factory. Filesystem implementations will use + * this ID to make a directory inside WAL directory path. * @return an open hbase:meta HRegion */ - private HRegion createNewMeta() throws IOException { + private HRegion createNewMeta(String walFactoryID) throws IOException { Path rootdir = FSUtils.getRootDir(getConf()); Configuration c = getConf(); HRegionInfo metaHRI = new HRegionInfo(HRegionInfo.FIRST_META_REGIONINFO); @@ -1402,9 +1403,8 @@ public class HBaseFsck extends Configured implements Closeable { Configuration confForWAL = new Configuration(c); confForWAL.set(HConstants.HBASE_DIR, rootdir.toString()); WAL wal = (new WALFactory(confForWAL, - Collections.singletonList(new MetricsWAL()), - "hbck-meta-recovery-" + RandomStringUtils.randomNumeric(8))). - getWAL(metaHRI.getEncodedNameAsBytes(), metaHRI.getTable().getNamespace()); + Collections. singletonList(new MetricsWAL()), walFactoryID)) + .getWAL(metaHRI.getEncodedNameAsBytes(), metaHRI.getTable().getNamespace()); HRegion meta = HRegion.createHRegion(metaHRI, rootdir, c, metaDescriptor, wal); MasterFileSystem.setInfoFamilyCachingForMeta(metaDescriptor, true); return meta; @@ -1513,7 +1513,8 @@ public class HBaseFsck extends Configured implements Closeable { Path backupDir = sidelineOldMeta(); LOG.info("Creating new hbase:meta"); - HRegion meta = createNewMeta(); + String walFactoryId = "hbck-meta-recovery-" + RandomStringUtils.randomNumeric(8); + HRegion meta = createNewMeta(walFactoryId); // populate meta List puts = generatePuts(tablesInfo); @@ -1527,11 +1528,31 @@ public class HBaseFsck extends Configured implements Closeable { if (meta.getWAL() != null) { meta.getWAL().close(); } + // clean up the temporary hbck meta recovery WAL directory + removeHBCKMetaRecoveryWALDir(walFactoryId); LOG.info("Success! hbase:meta table rebuilt."); LOG.info("Old hbase:meta is moved into " + backupDir); return true; } + /** + * Removes the empty Meta recovery WAL directory. + * @param walFactoryID A unique identifier for WAL factory which was used by Filesystem to make a + * Meta recovery WAL directory inside WAL directory path. + */ + private void removeHBCKMetaRecoveryWALDir(String walFactoryId) throws IOException { + Path rootdir = FSUtils.getRootDir(getConf()); + Path walLogDir = new Path(new Path(rootdir, HConstants.HREGION_LOGDIR_NAME), walFactoryId); + FileSystem fs = FSUtils.getCurrentFileSystem(getConf()); + FileStatus[] walFiles = FSUtils.listStatus(fs, walLogDir, null); + if (walFiles == null || walFiles.length == 0) { + LOG.info("HBCK meta recovery WAL directory is empty, removing it now."); + if (!FSUtils.deleteDirectory(fs, walLogDir)) { + LOG.warn("Couldn't clear the HBCK Meta recovery WAL directory " + walLogDir); + } + } + } + /** * Log an appropriate message about whether or not overlapping merges are computed in parallel. */ diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/hbck/TestOfflineMetaRebuildBase.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/hbck/TestOfflineMetaRebuildBase.java index 17a208f8331..15414156afe 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/hbck/TestOfflineMetaRebuildBase.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/hbck/TestOfflineMetaRebuildBase.java @@ -23,10 +23,15 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.io.IOException; import java.util.Arrays; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.fs.FileStatus; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.Admin; @@ -34,6 +39,7 @@ import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; import org.apache.hadoop.hbase.testclassification.MediumTests; import org.apache.hadoop.hbase.testclassification.MiscTests; +import org.apache.hadoop.hbase.util.FSUtils; import org.apache.hadoop.hbase.util.HBaseFsck; import org.apache.hadoop.hbase.util.HBaseFsck.ErrorReporter.ERROR_CODE; import org.junit.Test; @@ -68,6 +74,7 @@ public class TestOfflineMetaRebuildBase extends OfflineMetaRebuildTestCore { // rebuild meta table from scratch HBaseFsck fsck = new HBaseFsck(conf); assertTrue(fsck.rebuildMeta(false)); + assertTrue("HBCK meta recovery WAL directory exist.", validateHBCKMetaRecoveryWALDir()); // bring up the minicluster TEST_UTIL.startMiniZKCluster(); @@ -97,4 +104,22 @@ public class TestOfflineMetaRebuildBase extends OfflineMetaRebuildTestCore { LOG.info("Table " + table + " has " + tableRowCount(conf, table) + " entries."); assertEquals(16, tableRowCount(conf, table)); } + + /** + * Validate whether Meta recovery empty WAL directory is removed. + * @return True if directory is removed otherwise false. + */ + private boolean validateHBCKMetaRecoveryWALDir() throws IOException { + Path rootdir = FSUtils.getRootDir(TEST_UTIL.getConfiguration()); + Path walLogDir = new Path(rootdir, HConstants.HREGION_LOGDIR_NAME); + FileSystem fs = TEST_UTIL.getTestFileSystem(); + FileStatus[] walFiles = FSUtils.listStatus(fs, walLogDir, null); + assertNotNull(walFiles); + for (FileStatus fsStat : walFiles) { + if (fsStat.isDirectory() && fsStat.getPath().getName().startsWith("hbck-meta-recovery-")) { + return false; + } + } + return true; + } }