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
9 changes: 9 additions & 0 deletions hbase-hbck2/src/main/java/org/apache/hbase/HBCKFsUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ public static Path getRootDir(final Configuration c) throws IOException {
return p.makeQualified(fs.getUri(), fs.getWorkingDirectory());
}

/**
* @param conf must not be null
* @return Returns the filesystem of the hbase rootdir.
* @throws IOException from underlying FileSystem
*/
public static FileSystem getRootDirFileSystem(Configuration conf) throws IOException {
return getRootDir(conf).getFileSystem(conf);
}

/**
* Copy all files/subdirectories from source path to destination path.
*
Expand Down
32 changes: 19 additions & 13 deletions hbase-hbck2/src/main/java/org/apache/hbase/hbck1/HBaseFsck.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.util.ReflectionUtils;
import org.apache.hadoop.util.Tool;
import org.apache.hbase.HBCKFsUtils;
import org.apache.hbase.HBCKMetaTableAccessor;
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.yetus.audience.InterfaceStability;
Expand Down Expand Up @@ -274,6 +275,8 @@ public class HBaseFsck extends Configured implements Closeable {
private int retcode = 0;
private Path hbckLockPath;
private FSDataOutputStream hbckOutFd;
// single root file system instance to be used within HBaseFsck
private FileSystem rootFs;
// This lock is to prevent cleanup of balancer resources twice between
// ShutdownHook and the main code. We cleanup only if the connect() is
// successful
Expand Down Expand Up @@ -402,6 +405,7 @@ public HBaseFsck(Configuration conf, ExecutorService exec) throws MasterNotRunni
lockFileRetryCounterFactory = createLockRetryCounterFactory(getConf());
createZNodeRetryCounterFactory = createZnodeRetryCounterFactory(getConf());
zkw = createZooKeeperWatcher();
rootFs = HBCKFsUtils.getRootDirFileSystem(conf);
}

/**
Expand Down Expand Up @@ -433,13 +437,13 @@ private static RetryCounterFactory createZnodeRetryCounterFactory(Configuration
*/
@VisibleForTesting
public static Path getTmpDir(Configuration conf) throws IOException {
return new Path(CommonFSUtils.getRootDir(conf), HConstants.HBASE_TEMP_DIRECTORY);
return new Path(HBCKFsUtils.getRootDir(conf), HConstants.HBASE_TEMP_DIRECTORY);
}

/**
* Creates an hbck lock file.
*/
private static class FileLockCallable implements Callable<FSDataOutputStream> {
static class FileLockCallable implements Callable<FSDataOutputStream> {
RetryCounter retryCounter;
private final Configuration conf;
private Path hbckLockPath = null;
Expand All @@ -465,10 +469,11 @@ Path getHbckLockPath() {
@Override
public FSDataOutputStream call() throws IOException {
try {
FileSystem fs = CommonFSUtils.getCurrentFileSystem(this.conf);
// tmpDir is created based on hbase.rootdir
Path tmpDir = getTmpDir(conf);
FileSystem fs = tmpDir.getFileSystem(conf);
FsPermission defaultPerms = CommonFSUtils.getFilePermissions(fs, this.conf,
HConstants.DATA_FILE_UMASK_KEY);
Path tmpDir = getTmpDir(conf);
this.hbckLockPath = new Path(tmpDir, this.lockFileName);
fs.mkdirs(tmpDir);
final FSDataOutputStream out = createFileWithRetries(fs, this.hbckLockPath, defaultPerms);
Expand Down Expand Up @@ -559,7 +564,7 @@ private void unlockHbck() {
do {
try {
IOUtils.closeQuietly(hbckOutFd);
CommonFSUtils.delete(CommonFSUtils.getCurrentFileSystem(getConf()), hbckLockPath, true);
HBCKFsUtils.delete(rootFs, hbckLockPath, true);
return;
} catch (IOException ioe) {
LOG.info("Failed to delete " + hbckLockPath + ", try="
Expand Down Expand Up @@ -1535,8 +1540,7 @@ private void loadHdfsRegioninfo(HbckInfo hbi) throws IOException {
return;
}

FileSystem fs = FileSystem.get(getConf());
RegionInfo hri = HRegionFileSystem.loadRegionInfoFileContent(fs, regionDir);
RegionInfo hri = HRegionFileSystem.loadRegionInfoFileContent(rootFs, regionDir);
LOG.debug("RegionInfo read: " + hri.toString());
hbi.hdfsEntry.hri = hri;
}
Expand Down Expand Up @@ -1927,7 +1931,7 @@ public boolean rebuildMeta() throws IOException, InterruptedException {
HBaseTestingUtility.closeRegionAndWAL(meta);
// Clean out the WAL we created and used here.
LOG.info("Deleting {}, result={}", waldir,
CommonFSUtils.delete(FileSystem.get(getConf()), waldir, true));
HBCKFsUtils.delete(waldir.getFileSystem(getConf()), waldir, true));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not on this patch. But here is an issue. The actual delete() call happening within a Log statement. If INFO level not enabled, the delete wont get called. Can we fix that also here pls?

}
LOG.info("Success! hbase:meta table rebuilt. Old hbase:meta moved into " + backupDir);
return true;
Expand Down Expand Up @@ -3500,7 +3504,6 @@ void removeParentsAndFixSplits(Collection<HbckInfo> overlap) throws IOException
return;
}

FileSystem fs = FileSystem.get(conf);
LOG.info("Found parent: " + parent.getRegionNameAsString());
LOG.info("Found potential daughter a: " + daughterA.getRegionNameAsString());
LOG.info("Found potential daughter b: " + daughterB.getRegionNameAsString());
Expand Down Expand Up @@ -3528,7 +3531,7 @@ void removeParentsAndFixSplits(Collection<HbckInfo> overlap) throws IOException
return;
}

sidelineRegionDir(fs, parent);
sidelineRegionDir(rootFs, parent);
LOG.info("[" + thread + "] Sidelined parent region dir "+ parent.getHdfsRegionDir() +
" into " + getSidelineDir());
debugLsr(parent.getHdfsRegionDir());
Expand Down Expand Up @@ -3624,7 +3627,6 @@ void sidelineBigOverlaps(
}
List<HbckInfo> regionsToSideline =
RegionSplitCalculator.findBigRanges(bigOverlap, overlapsToSideline);
FileSystem fs = FileSystem.get(conf);
for (HbckInfo regionToSideline: regionsToSideline) {
try {
LOG.info("Closing region: " + regionToSideline);
Expand All @@ -3643,7 +3645,7 @@ void sidelineBigOverlaps(
}

LOG.info("Before sideline big overlapped region: " + regionToSideline.toString());
Path sidelineRegionDir = sidelineRegionDir(fs, TO_BE_LOADED, regionToSideline);
Path sidelineRegionDir = sidelineRegionDir(rootFs, TO_BE_LOADED, regionToSideline);
if (sidelineRegionDir != null) {
sidelinedRegions.put(sidelineRegionDir, regionToSideline);
LOG.info("After sidelined big overlapped region: "
Expand Down Expand Up @@ -5441,7 +5443,7 @@ public HBaseFsck exec(ExecutorService exec, String[] args)
tableDirs.add(CommonFSUtils.getTableDir(rootdir, t));
}
} else {
tableDirs = FSUtils.getTableDirs(CommonFSUtils.getCurrentFileSystem(getConf()), rootdir);
tableDirs = FSUtils.getTableDirs(rootFs, rootdir);
}
hfcc.checkTables(tableDirs);
hfcc.report(errors);
Expand Down Expand Up @@ -5616,4 +5618,8 @@ public static void debugLsr(Configuration conf,
}
}
}

FileSystem getRootFs() {
return rootFs;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.apache.hadoop.hbase.util.FSUtils.FamilyDirFilter;
import org.apache.hadoop.hbase.util.FSUtils.HFileFilter;
import org.apache.hadoop.hbase.util.FSUtils.RegionDirFilter;
import org.apache.hbase.HBCKFsUtils;
import org.apache.yetus.audience.InterfaceAudience;

import org.slf4j.Logger;
Expand Down Expand Up @@ -84,7 +85,7 @@ public class HFileCorruptionChecker {
public HFileCorruptionChecker(Configuration conf, ExecutorService executor,
boolean quarantine) throws IOException {
this.conf = conf;
this.fs = FileSystem.get(conf);
this.fs = HBCKFsUtils.getRootDirFileSystem(conf);
this.cacheConf = CacheConfig.DISABLED;
this.executor = executor;
this.inQuarantineMode = quarantine;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class TestHBCKFsTableDescriptorForceCreation {
public void testShouldCreateNewTableDescriptorIfForcefulCreationIsFalse()
throws IOException {
final String name = this.name.getMethodName();
FileSystem fs = FileSystem.get(UTIL.getConfiguration());
FileSystem fs = HBCKFsUtils.getRootDirFileSystem(UTIL.getConfiguration());
Path rootdir = new Path(UTIL.getDataTestDir(), name);
HBCKFsTableDescriptors fstd = new HBCKFsTableDescriptors(fs, rootdir);

Expand All @@ -68,7 +68,7 @@ public void testShouldCreateNewTableDescriptorIfForcefulCreationIsFalse()
public void testShouldNotCreateTheSameTableDescriptorIfForcefulCreationIsFalse()
throws IOException {
final String name = this.name.getMethodName();
FileSystem fs = FileSystem.get(UTIL.getConfiguration());
FileSystem fs = HBCKFsUtils.getRootDirFileSystem(UTIL.getConfiguration());
// Cleanup old tests if any detritus laying around.
Path rootdir = new Path(UTIL.getDataTestDir(), name);
HBCKFsTableDescriptors fstd = new HBCKFsTableDescriptors(fs, rootdir);
Expand All @@ -83,7 +83,7 @@ public void testShouldNotCreateTheSameTableDescriptorIfForcefulCreationIsFalse()
public void testShouldAllowForcefulCreationOfAlreadyExistingTableDescriptor()
throws Exception {
final String name = this.name.getMethodName();
FileSystem fs = FileSystem.get(UTIL.getConfiguration());
FileSystem fs = HBCKFsUtils.getRootDirFileSystem(UTIL.getConfiguration());
Path rootdir = new Path(UTIL.getDataTestDir(), name);
HBCKFsTableDescriptors fstd = new HBCKFsTableDescriptors(fs, rootdir);
TableDescriptor htd = TableDescriptorBuilder.newBuilder(TableName.valueOf(name)).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private Path assertWriteAndReadSequenceId(final int i) {

@Test public void testReadingHTDFromFS() throws IOException {
final String name = this.name.getMethodName();
FileSystem fs = FileSystem.get(UTIL.getConfiguration());
FileSystem fs = HBCKFsUtils.getRootDirFileSystem(UTIL.getConfiguration());
TableDescriptor htd = TableDescriptorBuilder.newBuilder(TableName.valueOf(name)).build();
Path rootdir = UTIL.getDataTestDir(name);
HBCKFsTableDescriptors fstd = new HBCKFsTableDescriptors(fs, rootdir);
Expand All @@ -120,7 +120,7 @@ private Path assertWriteAndReadSequenceId(final int i) {
@Test(expected = TableInfoMissingException.class)
public void testNoSuchTable() throws IOException {
final String name = "testNoSuchTable";
FileSystem fs = FileSystem.get(UTIL.getConfiguration());
FileSystem fs = HBCKFsUtils.getRootDirFileSystem(UTIL.getConfiguration());
// Cleanup old tests if any detrius laying around.
Path rootdir = new Path(UTIL.getDataTestDir(), name);
HBCKFsTableDescriptors htds = new HBCKFsTableDescriptors(fs, rootdir);
Expand Down Expand Up @@ -161,7 +161,7 @@ public void testCreateTableDescriptorUpdatesIfExistsAlready() throws IOException
Path testdir = UTIL.getDataTestDir(name.getMethodName());
final TableName name = TableName.valueOf(this.name.getMethodName());
TableDescriptor htd = TableDescriptorBuilder.newBuilder(name).build();
FileSystem fs = FileSystem.get(UTIL.getConfiguration());
FileSystem fs = HBCKFsUtils.getRootDirFileSystem(UTIL.getConfiguration());
HBCKFsTableDescriptors fstd = new HBCKFsTableDescriptors(fs, testdir);
assertTrue(fstd.createTableDescriptor(htd, false));
assertFalse(fstd.createTableDescriptor(htd, false));
Expand Down
124 changes: 124 additions & 0 deletions hbase-hbck2/src/test/java/org/apache/hbase/hbck1/TestHBaseFsck.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hbase.hbck1;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocalFileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.testclassification.MiscTests;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.apache.hbase.HBCKFsUtils;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.TestName;

@Category({MiscTests.class, SmallTests.class})
public class TestHBaseFsck {
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestHBaseFsck.class);

private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();

private String defaultRootDir;
private String nonDefaultRootDir;
private FileSystem testFileSystem;
private LocalFileSystem localFileSystem;
private Configuration conf;

@Rule
public TestName testName = new TestName();

@BeforeClass
public static void beforeClass() throws Exception {
TEST_UTIL.startMiniCluster(3);
}

@AfterClass
public static void afterClass() throws Exception {
TEST_UTIL.shutdownMiniCluster();
}

@Before
public void setup() throws IOException {
conf = TEST_UTIL.getConfiguration();
// the default is a hdfs directory
defaultRootDir = TEST_UTIL.getDataTestDirOnTestFS().toString();
localFileSystem = new LocalFileSystem();
testFileSystem = TEST_UTIL.getTestFileSystem();
nonDefaultRootDir =
TEST_UTIL.getRandomDir().makeQualified(localFileSystem.getUri(),
localFileSystem.getWorkingDirectory()).toString();
}

@Test
public void testHBaseRootDirWithSameFileSystemScheme() throws IOException,
ClassNotFoundException {
checkFileSystemScheme(defaultRootDir, testFileSystem.getUri().getScheme());
}

@Test
public void testHBaseRootDirWithDifferentFileSystemScheme() throws IOException,
ClassNotFoundException {
checkFileSystemScheme(nonDefaultRootDir, localFileSystem.getUri().getScheme());
}

private void checkFileSystemScheme(String hbaseRootDir, String expectedFsScheme)
throws IOException, ClassNotFoundException {
conf.set(HConstants.HBASE_DIR, hbaseRootDir);
HBaseFsck fsck = new HBaseFsck(conf);
String actualFsScheme = fsck.getRootFs().getScheme();
assertEquals(expectedFsScheme, actualFsScheme);
}

@Test
public void testFileLockCallableWithSetHBaseRootDir() throws IOException {
FileSystem fs = new Path(nonDefaultRootDir).getFileSystem(conf);
try {
assertNotEquals(TEST_UTIL.getTestFileSystem().getUri().getScheme(),
fs.getScheme());

conf.set(HConstants.HBASE_DIR, nonDefaultRootDir);
Path expectedLockFilePath = new Path(HBaseFsck.getTmpDir(conf), HBaseFsck.HBCK2_LOCK_FILE);
HBaseFsck.FileLockCallable fileLockCallable = new HBaseFsck.FileLockCallable(conf,
HBaseFsck.createLockRetryCounterFactory(conf).create());

assertTrue(!fs.exists(expectedLockFilePath));
// make a call and generate the hbck2 lock file to the non default file system
fileLockCallable.call();
assertTrue(fs.exists(expectedLockFilePath));
} finally {
HBCKFsUtils.delete(fs, new Path(nonDefaultRootDir), true);
}
}

}
Loading