From 6a20872e01380aa1d2bfa871aeb370023ce9bc2f Mon Sep 17 00:00:00 2001 From: Guanghao Zhang Date: Thu, 1 Aug 2019 08:54:47 +0800 Subject: [PATCH] HBASE-22737 Add a new admin method and shell cmd to trigger the hbck chore to run (#425) Signed-off-by: stack --- .../apache/hadoop/hbase/client/HBaseHbck.java | 56 +++++++++++-------- .../org/apache/hadoop/hbase/client/Hbck.java | 8 +++ .../src/main/protobuf/Master.proto | 13 +++++ .../apache/hadoop/hbase/master/HMaster.java | 12 ++-- .../{HbckChecker.java => HbckChore.java} | 18 +++--- .../hbase/master/MasterRpcServices.java | 23 +++++--- .../resources/hbase-webapps/master/hbck.jsp | 16 +++--- .../apache/hadoop/hbase/client/TestHbck.java | 15 +++++ ...estHbckChecker.java => TestHbckChore.java} | 36 ++++++------ hbase-shell/src/main/ruby/hbase/admin.rb | 7 +++ hbase-shell/src/main/ruby/shell.rb | 1 + .../ruby/shell/commands/hbck_chore_run.rb | 38 +++++++++++++ .../src/test/ruby/hbase/admin2_test.rb | 4 ++ 13 files changed, 177 insertions(+), 70 deletions(-) rename hbase-server/src/main/java/org/apache/hadoop/hbase/master/{HbckChecker.java => HbckChore.java} (95%) rename hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/{TestHbckChecker.java => TestHbckChore.java} (87%) create mode 100644 hbase-shell/src/main/ruby/shell/commands/hbck_chore_run.rb diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java index 64c9f46f269..07736b8c88a 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java @@ -19,27 +19,29 @@ package org.apache.hadoop.hbase.client; import java.io.IOException; import java.util.List; -import java.util.Map; import java.util.concurrent.Callable; import java.util.stream.Collectors; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.ServerName; -import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.ipc.RpcControllerFactory; -import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; -import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; -import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos; -import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableStateResponse; -import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.HbckService.BlockingInterface; - -import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; - import org.apache.yetus.audience.InterfaceAudience; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; +import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AssignsResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.BypassProcedureRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.BypassProcedureResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableStateResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.HbckService.BlockingInterface; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunHbckChoreRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunHbckChoreResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ScheduleServerCrashProcedureResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.UnassignsResponse; + +import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; /** * Use {@link ClusterConnection#getHbck()} to obtain an instance of {@link Hbck} instead of @@ -108,9 +110,8 @@ public class HBaseHbck implements Hbck { public List assigns(List encodedRegionNames, boolean override) throws IOException { try { - MasterProtos.AssignsResponse response = - this.hbck.assigns(rpcControllerFactory.newController(), - RequestConverter.toAssignRegionsRequest(encodedRegionNames, override)); + AssignsResponse response = this.hbck.assigns(rpcControllerFactory.newController(), + RequestConverter.toAssignRegionsRequest(encodedRegionNames, override)); return response.getPidList(); } catch (ServiceException se) { LOG.debug(toCommaDelimitedString(encodedRegionNames), se); @@ -122,9 +123,8 @@ public class HBaseHbck implements Hbck { public List unassigns(List encodedRegionNames, boolean override) throws IOException { try { - MasterProtos.UnassignsResponse response = - this.hbck.unassigns(rpcControllerFactory.newController(), - RequestConverter.toUnassignRegionsRequest(encodedRegionNames, override)); + UnassignsResponse response = this.hbck.unassigns(rpcControllerFactory.newController(), + RequestConverter.toUnassignRegionsRequest(encodedRegionNames, override)); return response.getPidList(); } catch (ServiceException se) { LOG.debug(toCommaDelimitedString(encodedRegionNames), se); @@ -140,13 +140,13 @@ public class HBaseHbck implements Hbck { public List bypassProcedure(List pids, long waitTime, boolean override, boolean recursive) throws IOException { - MasterProtos.BypassProcedureResponse response = ProtobufUtil.call( - new Callable() { + BypassProcedureResponse response = ProtobufUtil.call( + new Callable() { @Override - public MasterProtos.BypassProcedureResponse call() throws Exception { + public BypassProcedureResponse call() throws Exception { try { return hbck.bypassProcedure(rpcControllerFactory.newController(), - MasterProtos.BypassProcedureRequest.newBuilder().addAllProcId(pids). + BypassProcedureRequest.newBuilder().addAllProcId(pids). setWaitTime(waitTime).setOverride(override).setRecursive(recursive).build()); } catch (Throwable t) { LOG.error(pids.stream().map(i -> i.toString()). @@ -162,7 +162,7 @@ public class HBaseHbck implements Hbck { public List scheduleServerCrashProcedures(List serverNames) throws IOException { try { - MasterProtos.ScheduleServerCrashProcedureResponse response = + ScheduleServerCrashProcedureResponse response = this.hbck.scheduleServerCrashProcedure(rpcControllerFactory.newController(), RequestConverter.toScheduleServerCrashProcedureRequest(serverNames)); return response.getPidList(); @@ -174,4 +174,16 @@ public class HBaseHbck implements Hbck { throw new IOException(se); } } + + @Override + public boolean runHbckChore() throws IOException { + try { + RunHbckChoreResponse response = this.hbck.runHbckChore(rpcControllerFactory.newController(), + RunHbckChoreRequest.newBuilder().build()); + return response.getRan(); + } catch (ServiceException se) { + LOG.debug("Failed to run HBCK chore", se); + throw new IOException(se); + } + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java index aa7d38a0bae..0d29fec157b 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java @@ -122,4 +122,12 @@ public interface Hbck extends Abortable, Closeable { } List scheduleServerCrashProcedures(List serverNames) throws IOException; + + /** + * Request HBCK chore to run at master side. + * + * @return true if HBCK chore ran, false if HBCK chore already running + * @throws IOException if a remote or network exception occurs + */ + boolean runHbckChore() throws IOException; } diff --git a/hbase-protocol-shaded/src/main/protobuf/Master.proto b/hbase-protocol-shaded/src/main/protobuf/Master.proto index 2ddc542ea94..003447aebe1 100644 --- a/hbase-protocol-shaded/src/main/protobuf/Master.proto +++ b/hbase-protocol-shaded/src/main/protobuf/Master.proto @@ -358,6 +358,13 @@ message IsNormalizerEnabledResponse { required bool enabled = 1; } +message RunHbckChoreRequest { +} + +message RunHbckChoreResponse { + required bool ran = 1; +} + message RunCatalogScanRequest { } @@ -1134,4 +1141,10 @@ service HbckService { /** Schedule a ServerCrashProcedure to help recover a crash server */ rpc ScheduleServerCrashProcedure(ScheduleServerCrashProcedureRequest) returns(ScheduleServerCrashProcedureResponse); + + /** + * Request HBCK chore to run at master side. + */ + rpc RunHbckChore(RunHbckChoreRequest) + returns(RunHbckChoreResponse); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java index 6c89f8805c1..b397bf677f6 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java @@ -378,7 +378,7 @@ public class HMaster extends HRegionServer implements MasterServices { private ClusterStatusPublisher clusterStatusPublisherChore = null; private SnapshotCleanerChore snapshotCleanerChore = null; - private HbckChecker hbckChecker; + private HbckChore hbckChore; CatalogJanitor catalogJanitorChore; private LogCleaner logCleaner; private HFileCleaner hfileCleaner; @@ -1092,8 +1092,8 @@ public class HMaster extends HRegionServer implements MasterServices { getChoreService().scheduleChore(normalizerChore); this.catalogJanitorChore = new CatalogJanitor(this); getChoreService().scheduleChore(catalogJanitorChore); - this.hbckChecker = new HbckChecker(this); - getChoreService().scheduleChore(hbckChecker); + this.hbckChore = new HbckChore(this); + getChoreService().scheduleChore(hbckChore); // NAMESPACE READ!!!! // Here we expect hbase:namespace to be online. See inside initClusterSchemaService. @@ -1567,7 +1567,7 @@ public class HMaster extends HRegionServer implements MasterServices { choreService.cancelChore(this.hfileCleaner); choreService.cancelChore(this.replicationBarrierCleaner); choreService.cancelChore(this.snapshotCleanerChore); - choreService.cancelChore(this.hbckChecker); + choreService.cancelChore(this.hbckChore); } } @@ -3709,7 +3709,7 @@ public class HMaster extends HRegionServer implements MasterServices { return super.getWalGroupsReplicationStatus(); } - public HbckChecker getHbckChecker() { - return this.hbckChecker; + public HbckChore getHbckChore() { + return this.hbckChore; } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HbckChecker.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HbckChore.java similarity index 95% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/HbckChecker.java rename to hbase-server/src/main/java/org/apache/hadoop/hbase/master/HbckChore.java index fbc2c707275..6a69bae09c9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HbckChecker.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HbckChore.java @@ -47,11 +47,11 @@ import org.apache.hbase.thirdparty.com.google.common.collect.Lists; */ @InterfaceAudience.Private @InterfaceStability.Evolving -public class HbckChecker extends ScheduledChore { - private static final Logger LOG = LoggerFactory.getLogger(HbckChecker.class.getName()); +public class HbckChore extends ScheduledChore { + private static final Logger LOG = LoggerFactory.getLogger(HbckChore.class.getName()); - private static final String HBCK_CHECKER_INTERVAL = "hbase.master.hbck.checker.interval"; - private static final int DEFAULT_HBCK_CHECKER_INTERVAL = 60 * 60 * 1000; + private static final String HBCK_CHORE_INTERVAL = "hbase.master.hbck.chore.interval"; + private static final int DEFAULT_HBCK_CHORE_INTERVAL = 60 * 60 * 1000; private final MasterServices master; @@ -100,14 +100,14 @@ public class HbckChecker extends ScheduledChore { private volatile long checkingStartTimestamp = 0; private volatile long checkingEndTimestamp = 0; - public HbckChecker(MasterServices master) { - super("HbckChecker-", master, - master.getConfiguration().getInt(HBCK_CHECKER_INTERVAL, DEFAULT_HBCK_CHECKER_INTERVAL)); + public HbckChore(MasterServices master) { + super("HbckChore-", master, + master.getConfiguration().getInt(HBCK_CHORE_INTERVAL, DEFAULT_HBCK_CHORE_INTERVAL)); this.master = master; } @Override - protected void chore() { + protected synchronized void chore() { running = true; regionInfoMap.clear(); orphanRegionsOnRS.clear(); @@ -277,6 +277,6 @@ public class HbckChecker extends ScheduledChore { * Used for web ui to show when the HBCK checking report generated. */ public long getCheckingEndTimestamp() { - return this.checkingStartTimestamp; + return this.checkingEndTimestamp; } } \ No newline at end of file diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java index 1d4ae9c2e1b..000d7f41ac9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java @@ -49,7 +49,6 @@ import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; import org.apache.hadoop.hbase.client.MasterSwitchType; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionInfoBuilder; -import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.client.TableDescriptor; import org.apache.hadoop.hbase.client.TableState; @@ -68,10 +67,7 @@ import org.apache.hadoop.hbase.ipc.RpcServer.BlockingServiceAndInterface; import org.apache.hadoop.hbase.ipc.RpcServerFactory; import org.apache.hadoop.hbase.ipc.RpcServerInterface; import org.apache.hadoop.hbase.ipc.ServerRpcController; -import org.apache.hadoop.hbase.master.assignment.MergeTableRegionsProcedure; -import org.apache.hadoop.hbase.master.assignment.RegionStateStore; import org.apache.hadoop.hbase.master.assignment.RegionStates; -import org.apache.hadoop.hbase.master.assignment.SplitTableRegionProcedure; import org.apache.hadoop.hbase.master.locking.LockProcedure; import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil; @@ -91,7 +87,6 @@ import org.apache.hadoop.hbase.quotas.MasterQuotaManager; import org.apache.hadoop.hbase.quotas.QuotaObserverChore; import org.apache.hadoop.hbase.quotas.QuotaUtil; import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot; -import org.apache.hadoop.hbase.regionserver.HRegionFileSystem; import org.apache.hadoop.hbase.regionserver.RSRpcServices; import org.apache.hadoop.hbase.regionserver.RpcSchedulerFactory; import org.apache.hadoop.hbase.replication.ReplicationException; @@ -112,10 +107,8 @@ import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils; import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; -import org.apache.hadoop.hbase.util.FSUtils; import org.apache.hadoop.hbase.util.ForeignExceptionUtil; import org.apache.hadoop.hbase.util.Pair; -import org.apache.hadoop.hbase.util.PairOfSameType; import org.apache.hadoop.hbase.wal.AbstractFSWALProvider; import org.apache.hadoop.hbase.zookeeper.MetaTableLocator; import org.apache.yetus.audience.InterfaceAudience; @@ -264,6 +257,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCatalog import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCatalogScanResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCleanerChoreRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCleanerChoreResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunHbckChoreRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunHbckChoreResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SecurityCapabilitiesRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SecurityCapabilitiesResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningRequest; @@ -2337,6 +2332,20 @@ public class MasterRpcServices extends RSRpcServices // HBCK Services + @Override + public RunHbckChoreResponse runHbckChore(RpcController c, RunHbckChoreRequest req) + throws ServiceException { + rpcPreCheck("runHbckChore"); + LOG.info("{} request HBCK chore to run", master.getClientIdAuditPrefix()); + HbckChore hbckChore = master.getHbckChore(); + boolean ran = false; + if (!hbckChore.isRunning()) { + hbckChore.chore(); + ran = true; + } + return RunHbckChoreResponse.newBuilder().setRan(ran).build(); + } + /** * Update state of the table in meta only. This is required by hbck in some situations to cleanup * stuck assign/ unassign regions procedures for the table. diff --git a/hbase-server/src/main/resources/hbase-webapps/master/hbck.jsp b/hbase-server/src/main/resources/hbase-webapps/master/hbck.jsp index a2adeb09c73..fc212e838c0 100644 --- a/hbase-server/src/main/resources/hbase-webapps/master/hbck.jsp +++ b/hbase-server/src/main/resources/hbase-webapps/master/hbck.jsp @@ -27,7 +27,7 @@ import="java.time.ZonedDateTime" import="java.time.format.DateTimeFormatter" %> -<%@ page import="org.apache.hadoop.hbase.master.HbckChecker" %> +<%@ page import="org.apache.hadoop.hbase.master.HbckChore" %> <%@ page import="org.apache.hadoop.hbase.master.HMaster" %> <%@ page import="org.apache.hadoop.hbase.ServerName" %> <%@ page import="org.apache.hadoop.hbase.util.Bytes" %> @@ -38,18 +38,18 @@ <% HMaster master = (HMaster) getServletContext().getAttribute(HMaster.MASTER); pageContext.setAttribute("pageTitle", "HBase Master HBCK Report: " + master.getServerName()); - HbckChecker hbckChecker = master.getHbckChecker(); + HbckChore hbckChore = master.getHbckChore(); Map>> inconsistentRegions = null; Map orphanRegionsOnRS = null; List orphanRegionsOnFS = null; long startTimestamp = 0; long endTimestamp = 0; - if (hbckChecker != null) { - inconsistentRegions = hbckChecker.getInconsistentRegions(); - orphanRegionsOnRS = hbckChecker.getOrphanRegionsOnRS(); - orphanRegionsOnFS = hbckChecker.getOrphanRegionsOnFS(); - startTimestamp = hbckChecker.getCheckingStartTimestamp(); - endTimestamp = hbckChecker.getCheckingEndTimestamp(); + if (hbckChore != null) { + inconsistentRegions = hbckChore.getInconsistentRegions(); + orphanRegionsOnRS = hbckChore.getOrphanRegionsOnRS(); + orphanRegionsOnFS = hbckChore.getOrphanRegionsOnFS(); + startTimestamp = hbckChore.getCheckingStartTimestamp(); + endTimestamp = hbckChore.getCheckingEndTimestamp(); } ZonedDateTime zdt = ZonedDateTime.ofInstant(Instant.ofEpochMilli(startTimestamp), ZoneId.systemDefault()); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java index 1d5503bfce9..7149d1b48be 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java @@ -37,6 +37,7 @@ import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor; import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; import org.apache.hadoop.hbase.coprocessor.MasterObserver; import org.apache.hadoop.hbase.coprocessor.ObserverContext; +import org.apache.hadoop.hbase.master.HMaster; import org.apache.hadoop.hbase.master.RegionState; import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.master.procedure.TableProcedureInterface; @@ -238,6 +239,20 @@ public class TestHbck { waitOnPids(pids); } + @Test + public void testRunHbckChore() throws Exception { + HMaster master = TEST_UTIL.getMiniHBaseCluster().getMaster(); + long endTimestamp = master.getHbckChore().getCheckingEndTimestamp(); + Hbck hbck = getHbck(); + boolean ran = false; + while (!ran) { + ran = hbck.runHbckChore(); + if (ran) { + assertTrue(master.getHbckChore().getCheckingEndTimestamp() > endTimestamp); + } + } + } + public static class FailingSplitAfterMetaUpdatedMasterObserver implements MasterCoprocessor, MasterObserver { public volatile CountDownLatch latch; diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestHbckChecker.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestHbckChore.java similarity index 87% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestHbckChecker.java rename to hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestHbckChore.java index 0bb4dc41c83..72a9aabc9f7 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestHbckChecker.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestHbckChore.java @@ -31,7 +31,7 @@ import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionInfoBuilder; -import org.apache.hadoop.hbase.master.HbckChecker; +import org.apache.hadoop.hbase.master.HbckChore; import org.apache.hadoop.hbase.testclassification.MasterTests; import org.apache.hadoop.hbase.testclassification.MediumTests; import org.apache.hadoop.hbase.util.Pair; @@ -43,19 +43,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Category({ MasterTests.class, MediumTests.class }) -public class TestHbckChecker extends TestAssignmentManagerBase { - private static final Logger LOG = LoggerFactory.getLogger(TestHbckChecker.class); +public class TestHbckChore extends TestAssignmentManagerBase { + private static final Logger LOG = LoggerFactory.getLogger(TestHbckChore.class); @ClassRule public static final HBaseClassTestRule CLASS_RULE = - HBaseClassTestRule.forClass(TestHbckChecker.class); + HBaseClassTestRule.forClass(TestHbckChore.class); - private HbckChecker hbckChecker; + private HbckChore hbckChore; @Before public void setUp() throws Exception { super.setUp(); - hbckChecker = new HbckChecker(master); + hbckChore = new HbckChore(master); } @Test @@ -65,9 +65,9 @@ public class TestHbckChecker extends TestAssignmentManagerBase { List serverNames = master.getServerManager().getOnlineServersList(); assertEquals(NSERVERS, serverNames.size()); - hbckChecker.choreForTesting(); + hbckChore.choreForTesting(); Map>> inconsistentRegions = - hbckChecker.getInconsistentRegions(); + hbckChore.getInconsistentRegions(); // Test for case1: Master thought this region opened, but no regionserver reported it. assertTrue(inconsistentRegions.containsKey(metaRegionName)); @@ -79,8 +79,8 @@ public class TestHbckChecker extends TestAssignmentManagerBase { // Reported right region location. Then not in problematic regions. am.reportOnlineRegions(locationInMeta, Collections.singleton(metaRegionNameAsBytes)); - hbckChecker.choreForTesting(); - inconsistentRegions = hbckChecker.getInconsistentRegions(); + hbckChore.choreForTesting(); + inconsistentRegions = hbckChore.getInconsistentRegions(); assertFalse(inconsistentRegions.containsKey(metaRegionName)); } @@ -97,9 +97,9 @@ public class TestHbckChecker extends TestAssignmentManagerBase { assertEquals(NSERVERS, serverNames.size()); // Test for case1: Master thought this region opened, but no regionserver reported it. - hbckChecker.choreForTesting(); + hbckChore.choreForTesting(); Map>> inconsistentRegions = - hbckChecker.getInconsistentRegions(); + hbckChore.getInconsistentRegions(); assertTrue(inconsistentRegions.containsKey(regionName)); Pair> pair = inconsistentRegions.get(regionName); ServerName locationInMeta = pair.getFirst(); @@ -113,8 +113,8 @@ public class TestHbckChecker extends TestAssignmentManagerBase { final ServerName anotherServer = serverNames.stream().filter(s -> !s.equals(tempLocationInMeta)).findFirst().get(); am.reportOnlineRegions(anotherServer, Collections.singleton(hri.getRegionName())); - hbckChecker.choreForTesting(); - inconsistentRegions = hbckChecker.getInconsistentRegions(); + hbckChore.choreForTesting(); + inconsistentRegions = hbckChore.getInconsistentRegions(); assertTrue(inconsistentRegions.containsKey(regionName)); pair = inconsistentRegions.get(regionName); locationInMeta = pair.getFirst(); @@ -125,8 +125,8 @@ public class TestHbckChecker extends TestAssignmentManagerBase { // Test for case3: More than one regionservers reported opened this region. am.reportOnlineRegions(locationInMeta, Collections.singleton(hri.getRegionName())); - hbckChecker.choreForTesting(); - inconsistentRegions = hbckChecker.getInconsistentRegions(); + hbckChore.choreForTesting(); + inconsistentRegions = hbckChore.getInconsistentRegions(); assertTrue(inconsistentRegions.containsKey(regionName)); pair = inconsistentRegions.get(regionName); locationInMeta = pair.getFirst(); @@ -137,8 +137,8 @@ public class TestHbckChecker extends TestAssignmentManagerBase { // Reported right region location. Then not in problematic regions. am.reportOnlineRegions(anotherServer, Collections.EMPTY_SET); - hbckChecker.choreForTesting(); - inconsistentRegions = hbckChecker.getInconsistentRegions(); + hbckChore.choreForTesting(); + inconsistentRegions = hbckChore.getInconsistentRegions(); assertFalse(inconsistentRegions.containsKey(regionName)); } } \ No newline at end of file diff --git a/hbase-shell/src/main/ruby/hbase/admin.rb b/hbase-shell/src/main/ruby/hbase/admin.rb index 65a60613300..b1b402122a0 100644 --- a/hbase-shell/src/main/ruby/hbase/admin.rb +++ b/hbase-shell/src/main/ruby/hbase/admin.rb @@ -37,6 +37,7 @@ module Hbase @connection = connection # Java Admin instance @admin = @connection.getAdmin + @hbck = @connection.getHbck @conf = @connection.getConfiguration end @@ -249,6 +250,12 @@ module Hbase @admin.isMasterInMaintenanceMode end + #---------------------------------------------------------------------------------------------- + # Request HBCK chore to run + def hbck_chore_run + @hbck.runHbckChore + end + #---------------------------------------------------------------------------------------------- # Request a scan of the catalog table (for garbage collection) # Returns an int signifying the number of entries cleaned diff --git a/hbase-shell/src/main/ruby/shell.rb b/hbase-shell/src/main/ruby/shell.rb index f8f865db3fb..3c6f48f2304 100644 --- a/hbase-shell/src/main/ruby/shell.rb +++ b/hbase-shell/src/main/ruby/shell.rb @@ -344,6 +344,7 @@ Shell.load_command_group( unassign zk_dump wal_roll + hbck_chore_run catalogjanitor_run catalogjanitor_switch catalogjanitor_enabled diff --git a/hbase-shell/src/main/ruby/shell/commands/hbck_chore_run.rb b/hbase-shell/src/main/ruby/shell/commands/hbck_chore_run.rb new file mode 100644 index 00000000000..4f77ead472a --- /dev/null +++ b/hbase-shell/src/main/ruby/shell/commands/hbck_chore_run.rb @@ -0,0 +1,38 @@ +# +# 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. +# + +module Shell + module Commands + class HbckChoreRun < Command + def help + <<-EOF +Request HBCK chore to run at master side. It will try to find the orphan +regions on RegionServer or FileSystem and find the inconsistent regions. +You can check the HBCK report at Master web UI. + + hbase> hbck_chore_run + +EOF + end + + def command + admin.hbck_chore_run + end + end + end +end diff --git a/hbase-shell/src/test/ruby/hbase/admin2_test.rb b/hbase-shell/src/test/ruby/hbase/admin2_test.rb index 607bce25a67..3af5ac0b4f3 100644 --- a/hbase-shell/src/test/ruby/hbase/admin2_test.rb +++ b/hbase-shell/src/test/ruby/hbase/admin2_test.rb @@ -73,6 +73,10 @@ module Hbase # Some text which isn't in the simple output assert output.include? 'regionsInTransition' end + + define_test 'hbck_chore_run' do + command(:hbck_chore_run) + end end # Simple administration methods tests