HBASE-20104 Fix infinite loop of RIT when creating table on a rsgroup that has 
no online servers


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/ee1f26c4
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/ee1f26c4
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/ee1f26c4

Branch: refs/heads/HBASE-19064
Commit: ee1f26c4bbb5490e257eee63933fd3943f102a7d
Parents: 776eb5d
Author: haxiaolin <haxiao...@xiaomi.com>
Authored: Thu Mar 1 08:34:31 2018 -0800
Committer: tedyu <yuzhih...@gmail.com>
Committed: Thu Mar 1 08:34:31 2018 -0800

----------------------------------------------------------------------
 .../hbase/rsgroup/RSGroupAdminEndpoint.java     | 33 +++++++++++++++
 .../hadoop/hbase/rsgroup/TestRSGroupsBase.java  | 43 ++++++++++++++++++++
 2 files changed, 76 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/ee1f26c4/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 7fec32d..624aa44 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
@@ -31,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;
@@ -352,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())
@@ -374,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/ee1f26c4/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 76bcd20..fef3a5e 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
@@ -999,4 +999,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;
+      }
+    });
+  }
 }

Reply via email to