From f0226921edebc1d6e551ac9fa1f3db2f39756c12 Mon Sep 17 00:00:00 2001 From: Duo Zhang Date: Thu, 2 Sep 2021 16:39:09 +0800 Subject: [PATCH] HBASE-26157 Expose some IA.LimitedPrivate interface in TestingHBaseCluster (#3643) Signed-off-by: Geoffrey Jacoby --- .../hbase/testing/TestingHBaseCluster.java | 41 +++++++ .../testing/TestingHBaseClusterImpl.java | 41 +++++++ .../testing/TestTestingHBaseCluster.java | 7 ++ .../TestTestingHBaseClusterImplForCPs.java | 107 ++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseClusterImplForCPs.java diff --git a/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseCluster.java b/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseCluster.java index b4d4e563fa6..d59c6db2e6a 100644 --- a/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseCluster.java +++ b/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseCluster.java @@ -17,9 +17,15 @@ */ package org.apache.hadoop.hbase.testing; +import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HBaseInterfaceAudience; import org.apache.hadoop.hbase.ServerName; +import org.apache.hadoop.hbase.client.RegionInfo; +import org.apache.hadoop.hbase.regionserver.OnlineRegions; +import org.apache.hadoop.hbase.regionserver.Region; import org.apache.yetus.audience.InterfaceAudience; /** @@ -114,6 +120,41 @@ public interface TestingHBaseCluster { */ void start() throws Exception; + /** + * Get the address of active master if there is one. + */ + Optional getActiveMasterAddress(); + + /** + * Get all the backup master addresses. + */ + List getBackupMasterAddresses(); + + /** + * Get all the region server addresses. + */ + List getRegionServerAddresses(); + + /** + * Get the server side {@link Region} interface for the specific region. + *

+ * This is used for CPs to test something which can only be accessed at server side, such as tags. + */ + @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC) + Optional getRegion(RegionInfo regionInfo); + + /** + * Get the server side {@link OnlineRegions} interface for the specific region server. + *

+ * You could list the addresses of all the region server through the + * {@link #getRegionServerAddresses()} method. + *

+ * This is used for CPs to test something which can only be accessed at server side, such as tags. + * And also you could use the returned interface to get all regions on this region server, etc. + */ + @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC) + Optional getOnlineRegionsInterface(ServerName serverName); + /** * Return whether the cluster is running. *

diff --git a/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseClusterImpl.java b/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseClusterImpl.java index 5128b907820..8cea789ab68 100644 --- a/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseClusterImpl.java +++ b/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseClusterImpl.java @@ -18,13 +18,20 @@ package org.apache.hadoop.hbase.testing; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.stream.Collectors; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseTestingUtil; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.StartTestingClusterOption; +import org.apache.hadoop.hbase.client.RegionInfo; +import org.apache.hadoop.hbase.master.HMaster; +import org.apache.hadoop.hbase.regionserver.HRegion; +import org.apache.hadoop.hbase.regionserver.OnlineRegions; +import org.apache.hadoop.hbase.regionserver.Region; import org.apache.hadoop.hbase.util.JVMClusterUtil.MasterThread; import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread; import org.apache.yetus.audience.InterfaceAudience; @@ -172,4 +179,38 @@ class TestingHBaseClusterImpl implements TestingHBaseCluster { public void startRegionServer(String hostname, int port) throws Exception { util.getMiniHBaseCluster().startRegionServer(hostname, port); } + + @Override + public Optional getActiveMasterAddress() { + return Optional.ofNullable(util.getMiniHBaseCluster().getMaster()).map(HMaster::getServerName); + } + + @Override + public List getBackupMasterAddresses() { + return util.getMiniHBaseCluster().getMasterThreads().stream().map(MasterThread::getMaster) + .filter(m -> !m.isActiveMaster()).map(HMaster::getServerName).collect(Collectors.toList()); + } + + @Override + public List getRegionServerAddresses() { + return util.getMiniHBaseCluster().getRegionServerThreads().stream() + .map(t -> t.getRegionServer().getServerName()).collect(Collectors.toList()); + } + + @Override + public Optional getRegion(RegionInfo regionInfo) { + for (RegionServerThread t : util.getMiniHBaseCluster().getRegionServerThreads()) { + for (HRegion region : t.getRegionServer().getRegions()) { + if (region.getRegionInfo().equals(regionInfo)) { + return Optional.of(region); + } + } + } + return Optional.empty(); + } + + @Override + public Optional getOnlineRegionsInterface(ServerName serverName) { + return Optional.ofNullable(util.getMiniHBaseCluster().getRegionServer(serverName)); + } } diff --git a/hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseCluster.java b/hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseCluster.java index 33e7103e760..4ff7450e8f3 100644 --- a/hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseCluster.java +++ b/hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseCluster.java @@ -144,4 +144,11 @@ public class TestTestingHBaseCluster { CLUSTER.startRegionServer(DNS.getHostname(CLUSTER.getConf(), ServerType.REGIONSERVER), 0); Waiter.waitFor(CLUSTER.getConf(), 30000, () -> admin.getRegionServers().size() == 4); } + + @Test + public void testGetAddresses() throws Exception { + assertTrue(CLUSTER.getActiveMasterAddress().isPresent()); + assertEquals(1, CLUSTER.getBackupMasterAddresses().size()); + assertEquals(3, CLUSTER.getRegionServerAddresses().size()); + } } diff --git a/hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseClusterImplForCPs.java b/hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseClusterImplForCPs.java new file mode 100644 index 00000000000..322bd37e09b --- /dev/null +++ b/hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseClusterImplForCPs.java @@ -0,0 +1,107 @@ +/** + * 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.hadoop.hbase.testing; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; + +import java.io.IOException; +import java.util.List; +import org.apache.hadoop.hbase.HBaseClassTestRule; +import org.apache.hadoop.hbase.ServerName; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Admin; +import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; +import org.apache.hadoop.hbase.client.Connection; +import org.apache.hadoop.hbase.client.ConnectionFactory; +import org.apache.hadoop.hbase.client.RegionInfo; +import org.apache.hadoop.hbase.client.RegionInfoBuilder; +import org.apache.hadoop.hbase.client.RegionLocator; +import org.apache.hadoop.hbase.client.TableDescriptorBuilder; +import org.apache.hadoop.hbase.regionserver.OnlineRegions; +import org.apache.hadoop.hbase.regionserver.Region; +import org.apache.hadoop.hbase.testclassification.LargeTests; +import org.apache.hadoop.hbase.testclassification.MiscTests; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import org.apache.hbase.thirdparty.com.google.common.io.Closeables; + +@Category({ MiscTests.class, LargeTests.class }) +public class TestTestingHBaseClusterImplForCPs { + + @ClassRule + public static final HBaseClassTestRule CLASS_RULE = + HBaseClassTestRule.forClass(TestTestingHBaseClusterImplForCPs.class); + + private static TestingHBaseCluster CLUSTER; + + private static TableName NAME = TableName.valueOf("test"); + + private static byte[] CF = Bytes.toBytes("cf"); + + private static Connection CONN; + + private static Admin ADMIN; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + CLUSTER = TestingHBaseCluster.create(TestingHBaseClusterOption.builder().numMasters(2) + .numRegionServers(3).numDataNodes(3).build()); + CLUSTER.start(); + CONN = ConnectionFactory.createConnection(CLUSTER.getConf()); + ADMIN = CONN.getAdmin(); + ADMIN.createTable(TableDescriptorBuilder.newBuilder(NAME) + .setColumnFamily(ColumnFamilyDescriptorBuilder.of(CF)).build()); + ADMIN.balancerSwitch(false, true); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + Closeables.close(ADMIN, true); + Closeables.close(CONN, true); + if (CLUSTER.isClusterRunning()) { + CLUSTER.stop(); + } + } + + @Test + public void testGetRegion() throws IOException { + List infos = ADMIN.getRegions(NAME); + assertEquals(1, infos.size()); + RegionInfo info = infos.get(0); + Region region = CLUSTER.getRegion(info).get(); + ServerName loc; + try (RegionLocator locator = CONN.getRegionLocator(NAME)) { + loc = locator.getRegionLocation(info.getStartKey()).getServerName(); + } + OnlineRegions onlineRegionsInterface = CLUSTER.getOnlineRegionsInterface(loc).get(); + List regions = onlineRegionsInterface.getRegions(NAME); + assertEquals(1, regions.size()); + assertSame(region, regions.get(0)); + + assertFalse(CLUSTER + .getRegion(RegionInfoBuilder.newBuilder(TableName.valueOf("whatever")).build()).isPresent()); + assertFalse(CLUSTER.getOnlineRegionsInterface(ServerName.valueOf("whatever,1,1")).isPresent()); + } +}