From 907d1f4753f25cc6238eb77cb34e5f44c381e5f7 Mon Sep 17 00:00:00 2001 From: Richard Antal Date: Wed, 25 Mar 2020 12:42:40 +0100 Subject: [PATCH] HBASE-24039 HBCK2 feature negotiation to check what commands are supported --- .../src/main/java/org/apache/hbase/HBCK2.java | 36 ++++++++++++++----- .../test/java/org/apache/hbase/TestHBCK2.java | 14 ++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/hbase-hbck2/src/main/java/org/apache/hbase/HBCK2.java b/hbase-hbck2/src/main/java/org/apache/hbase/HBCK2.java index ead69c4..c62a15f 100644 --- a/hbase-hbck2/src/main/java/org/apache/hbase/HBCK2.java +++ b/hbase-hbck2/src/main/java/org/apache/hbase/HBCK2.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; @@ -32,6 +33,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.Collections; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configured; @@ -102,6 +104,12 @@ public class HBCK2 extends Configured implements org.apache.hadoop.util.Tool { private Configuration conf; static final String [] MINIMUM_HBCK2_VERSION = {"2.0.3", "2.1.1", "2.2.0", "3.0.0"}; private boolean skipCheck = false; + static final Map > functionNameMap = new HashMap>() {{ + put(SET_TABLE_STATE, Arrays.asList("setTableStateInMeta")); + put(BYPASS, Arrays.asList("bypassProcedure")); + put(SCHEDULE_RECOVERIES, Arrays.asList("scheduleServerCrashProcedure", + "scheduleServerCrashProcedures")); + }}; /** * Wait 1ms on lock by default. @@ -133,6 +141,19 @@ public class HBCK2 extends Configured implements org.apache.hadoop.util.Tool { } } + void checkFunctionSupported(ClusterConnection connection, String cmd) throws IOException { + if (skipCheck) { + LOG.info("Skipped {} command version check; 'skip' set", cmd); + return; + } + List methods = Arrays.asList(connection.getHbck().getClass().getDeclaredMethods()); + List finalCmds = functionNameMap.getOrDefault(cmd, Collections.singletonList(cmd)); + boolean supported = methods.stream().anyMatch(method -> finalCmds.contains(method.getName())); + if (!supported) { + throw new UnsupportedOperationException("Unsupported command" + cmd); + } + } + TableState setTableState(Hbck hbck, TableName tableName, TableState.State state) throws IOException { return hbck.setTableStateInMeta(new TableState(tableName, state)); @@ -324,7 +345,7 @@ public class HBCK2 extends Configured implements org.apache.hadoop.util.Tool { boolean recursiveFlag = commandLine.hasOption(recursive.getOpt()); List pids = Arrays.stream(pidStrs).map(Long::valueOf).collect(Collectors.toList()); try (ClusterConnection connection = connect(); Hbck hbck = connection.getHbck()) { - checkHBCKSupport(connection, BYPASS); + checkFunctionSupported(connection, BYPASS); return hbck.bypassProcedure(pids, lockWait, overrideFlag, recursiveFlag); } } @@ -727,7 +748,7 @@ public class HBCK2 extends Configured implements org.apache.hadoop.util.Tool { return EXIT_FAILURE; } try (ClusterConnection connection = connect(); Hbck hbck = connection.getHbck()) { - checkHBCKSupport(connection, command); + checkFunctionSupported(connection, command); System.out.println(setTableState(hbck, TableName.valueOf(commands[1]), TableState.State.valueOf(commands[2]))); } @@ -739,7 +760,7 @@ public class HBCK2 extends Configured implements org.apache.hadoop.util.Tool { return EXIT_FAILURE; } try (ClusterConnection connection = connect(); Hbck hbck = connection.getHbck()) { - checkHBCKSupport(connection, command); + checkFunctionSupported(connection, command); System.out.println(assigns(hbck, purgeFirst(commands))); } break; @@ -749,7 +770,7 @@ public class HBCK2 extends Configured implements org.apache.hadoop.util.Tool { showErrorMessage(command + " takes one or more pids"); return EXIT_FAILURE; } - // bypass does the connection setup and the checkHBCKSupport down + // bypass does the connection setup and the checkFunctionSupported down // inside in the bypass method delaying connection setup until last // moment. It does this because it has another set of command options // to process and wants to do that before setting up connection. @@ -768,7 +789,7 @@ public class HBCK2 extends Configured implements org.apache.hadoop.util.Tool { return EXIT_FAILURE; } try (ClusterConnection connection = connect(); Hbck hbck = connection.getHbck()) { - checkHBCKSupport(connection, command); + checkFunctionSupported(connection, command); System.out.println(toString(unassigns(hbck, purgeFirst(commands)))); } break; @@ -813,7 +834,7 @@ public class HBCK2 extends Configured implements org.apache.hadoop.util.Tool { return EXIT_FAILURE; } try (ClusterConnection connection = connect(); Hbck hbck = connection.getHbck()) { - checkHBCKSupport(connection, command, "2.0.3", "2.1.2", "2.2.0", "3.0.0"); + checkFunctionSupported(connection, command); System.out.println(toString(scheduleRecoveries(hbck, purgeFirst(commands)))); } break; @@ -824,8 +845,7 @@ public class HBCK2 extends Configured implements org.apache.hadoop.util.Tool { return EXIT_FAILURE; } try (ClusterConnection connection = connect(); Hbck hbck = connection.getHbck()) { - checkHBCKSupport(connection, command, "2.0.6", "2.1.6", "2.2.1", "2.3.0", - "3.0.0"); + checkFunctionSupported(connection, command); hbck.fixMeta(); System.out.println("Server-side processing of fixMeta triggered."); } diff --git a/hbase-hbck2/src/test/java/org/apache/hbase/TestHBCK2.java b/hbase-hbck2/src/test/java/org/apache/hbase/TestHBCK2.java index dd08b0f..51bc7bc 100644 --- a/hbase-hbck2/src/test/java/org/apache/hbase/TestHBCK2.java +++ b/hbase-hbck2/src/test/java/org/apache/hbase/TestHBCK2.java @@ -504,6 +504,20 @@ public class TestHBCK2 { assertFalse("Should not contain: " + expectedResult, result.contains(expectedResult)); } + @Test + public void testFunctionSupported() throws IOException { + try (ClusterConnection connection = this.hbck2.connect()) { + this.hbck2.checkFunctionSupported(connection, "scheduleRecoveries"); + } + } + + @Test (expected = UnsupportedOperationException.class) + public void testFunctionNotSupported() throws IOException { + try (ClusterConnection connection = this.hbck2.connect()) { + this.hbck2.checkFunctionSupported(connection, "test"); + } + } + private String testFormatExtraRegionsInMetaReport() throws IOException { return testFormatExtraRegionsInMeta(new String[]{HBCK2.EXTRA_REGIONS_IN_META }); } -- 2.21.1 (Apple Git-122.3)