HBASE-20104 Fix infinite loop of RIT when creating table on a rsgroup that has no online servers
Signed-off-by: tedyu <yuzhih...@gmail.com> Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/a08ade9f Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/a08ade9f Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/a08ade9f Branch: refs/heads/HBASE-19397-branch-2 Commit: a08ade9f1aa733b41b1f6fb0b5f7cd6643c4b8a9 Parents: a2bf2ad Author: haxiaolin <haxiao...@xiaomi.com> Authored: Wed Feb 28 19:15:57 2018 +0800 Committer: tedyu <yuzhih...@gmail.com> Committed: Thu Mar 1 08:34:58 2018 -0800 ---------------------------------------------------------------------- .../hbase/rsgroup/RSGroupAdminEndpoint.java | 34 +++++++++++++++- .../hadoop/hbase/rsgroup/TestRSGroupsBase.java | 43 ++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/a08ade9f/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java ---------------------------------------------------------------------- diff --git a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java index ce74bb4..0006d68 100644 --- a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java +++ b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java @@ -18,7 +18,6 @@ package org.apache.hadoop.hbase.rsgroup; - import com.google.protobuf.RpcCallback; import com.google.protobuf.RpcController; import com.google.protobuf.Service; @@ -32,6 +31,7 @@ import java.util.Set; import java.util.stream.Collectors; import org.apache.hadoop.hbase.CoprocessorEnvironment; +import org.apache.hadoop.hbase.HBaseIOException; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.NamespaceDescriptor; import org.apache.hadoop.hbase.ServerName; @@ -353,6 +353,27 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver { } } + boolean rsgroupHasServersOnline(TableDescriptor desc) throws IOException { + String groupName = + master.getClusterSchema().getNamespace(desc.getTableName().getNamespaceAsString()) + .getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP); + if (groupName == null) { + groupName = RSGroupInfo.DEFAULT_GROUP; + } + RSGroupInfo rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName); + if (rsGroupInfo == null) { + throw new ConstraintException( + "Default RSGroup (" + groupName + ") for this table's " + "namespace does not exist."); + } + + for (ServerName onlineServer : master.getServerManager().createDestinationServersList()) { + if (rsGroupInfo.getServers().contains(onlineServer.getAddress())) { + return true; + } + } + return false; + } + void assignTableToGroup(TableDescriptor desc) throws IOException { String groupName = master.getClusterSchema().getNamespace(desc.getTableName().getNamespaceAsString()) @@ -375,6 +396,17 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver { // MasterObserver overrides ///////////////////////////////////////////////////////////////////////////// + @Override + public void preCreateTableAction( + final ObserverContext<MasterCoprocessorEnvironment> ctx, + final TableDescriptor desc, + final RegionInfo[] regions) throws IOException { + if (!desc.getTableName().isSystemTable() && !rsgroupHasServersOnline(desc)) { + throw new HBaseIOException("No online servers in the rsgroup, which table " + + desc.getTableName().getNameAsString() + " belongs to"); + } + } + // Assign table to default RSGroup. @Override public void postCreateTable(ObserverContext<MasterCoprocessorEnvironment> ctx, http://git-wip-us.apache.org/repos/asf/hbase/blob/a08ade9f/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase.java ---------------------------------------------------------------------- diff --git a/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase.java b/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase.java index fdc29b3..9422bf8 100644 --- a/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase.java +++ b/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase.java @@ -997,4 +997,47 @@ public abstract class TestRSGroupsBase { assertFalse(newGroupServers.contains(targetServer.getAddress())); assertEquals(2, newGroupServers.size()); } + + @Test + public void testCreateWhenRsgroupNoOnlineServers() throws Exception { + LOG.info("testCreateWhenRsgroupNoOnlineServers"); + + // set rsgroup has no online servers and test create table + final RSGroupInfo appInfo = addGroup("appInfo", 1); + Iterator<Address> iterator = appInfo.getServers().iterator(); + List<ServerName> serversToDecommission = new ArrayList<>(); + ServerName targetServer = ServerName.parseServerName(iterator.next().toString()); + AdminProtos.AdminService.BlockingInterface targetRS = + ((ClusterConnection) admin.getConnection()).getAdmin(targetServer); + targetServer = ProtobufUtil.toServerName( + targetRS.getServerInfo(null, GetServerInfoRequest.newBuilder().build()).getServerInfo() + .getServerName()); + assertTrue(master.getServerManager().getOnlineServers().containsKey(targetServer)); + serversToDecommission.add(targetServer); + admin.decommissionRegionServers(serversToDecommission, true); + assertEquals(1, admin.listDecommissionedRegionServers().size()); + + final TableName tableName = TableName.valueOf(tablePrefix + "_ns", name.getMethodName()); + admin.createNamespace(NamespaceDescriptor.create(tableName.getNamespaceAsString()) + .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, appInfo.getName()).build()); + final HTableDescriptor desc = new HTableDescriptor(tableName); + desc.addFamily(new HColumnDescriptor("f")); + try { + admin.createTable(desc); + fail("Shouldn't create table successfully!"); + } catch (Exception e) { + LOG.debug("create table error", e); + } + + // recommission and test create table + admin.recommissionRegionServer(targetServer, null); + assertEquals(0, admin.listDecommissionedRegionServers().size()); + admin.createTable(desc); + // wait for created table to be assigned + TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() { + @Override public boolean evaluate() throws Exception { + return getTableRegionMap().get(desc.getTableName()) != null; + } + }); + } }