From c1e2bd5f70e5afb73ca281ff1ea4b67fb786ccac Mon Sep 17 00:00:00 2001 From: guluo Date: Wed, 20 Mar 2024 22:53:43 +0800 Subject: [PATCH 1/3] Fix issue of returning too slow --- .../hbase/client/AsyncRegionLocator.java | 80 +++++--- ...TableRegionLocatorWithRegionReplicaId.java | 174 ++++++++++++++++++ 2 files changed, 230 insertions(+), 24 deletions(-) create mode 100644 hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableRegionLocatorWithRegionReplicaId.java diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRegionLocator.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRegionLocator.java index da58dd8e1e53..e528e8b8f662 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRegionLocator.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRegionLocator.java @@ -35,6 +35,7 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; +import org.apache.hadoop.hbase.DoNotRetryIOException; import org.apache.hadoop.hbase.HRegionLocation; import org.apache.hadoop.hbase.RegionLocations; import org.apache.hadoop.hbase.ServerName; @@ -151,36 +152,67 @@ CompletableFuture getRegionLocations(TableName tableName, byte[ }, AsyncRegionLocator::getRegionNames, supplier); } + private void internalAddListener(CompletableFuture future, + CompletableFuture locsFuture, TableName tableName, byte[] row, int replicaId, + RegionLocateType type) { + addListener(locsFuture, (locs, error) -> { + if (error != null) { + future.completeExceptionally(error); + return; + } + HRegionLocation loc = locs.getRegionLocation(replicaId); + if (loc == null) { + future.completeExceptionally( + new RegionOfflineException("No location for " + tableName + ", row='" + + Bytes.toStringBinary(row) + "', locateType=" + type + ", replicaId=" + replicaId)); + } else if (loc.getServerName() == null) { + future + .completeExceptionally(new RegionOfflineException("No server address listed for region '" + + loc.getRegion().getRegionNameAsString() + ", row='" + Bytes.toStringBinary(row) + + "', locateType=" + type + ", replicaId=" + replicaId)); + } else { + future.complete(loc); + } + }); + } + CompletableFuture getRegionLocation(TableName tableName, byte[] row, int replicaId, RegionLocateType type, boolean reload, long timeoutNs) { final Supplier supplier = new TableSpanBuilder(conn) .setName("AsyncRegionLocator.getRegionLocation").setTableName(tableName); return tracedLocationFuture(() -> { - // meta region can not be split right now so we always call the same method. - // Change it later if the meta table can have more than one regions. CompletableFuture future = new CompletableFuture<>(); - CompletableFuture locsFuture = isMeta(tableName) - ? metaRegionLocator.getRegionLocations(replicaId, reload) - : nonMetaRegionLocator.getRegionLocations(tableName, row, replicaId, type, reload); - addListener(locsFuture, (locs, error) -> { - if (error != null) { - future.completeExceptionally(error); - return; - } - HRegionLocation loc = locs.getRegionLocation(replicaId); - if (loc == null) { - future.completeExceptionally( - new RegionOfflineException("No location for " + tableName + ", row='" - + Bytes.toStringBinary(row) + "', locateType=" + type + ", replicaId=" + replicaId)); - } else if (loc.getServerName() == null) { - future.completeExceptionally( - new RegionOfflineException("No server address listed for region '" - + loc.getRegion().getRegionNameAsString() + ", row='" + Bytes.toStringBinary(row) - + "', locateType=" + type + ", replicaId=" + replicaId)); - } else { - future.complete(loc); - } - }); + if (replicaId == RegionReplicaUtil.DEFAULT_REPLICA_ID) { + // meta region can not be split right now so we always call the same method. + // Change it later if the meta table can have more than one regions. + CompletableFuture locsFuture = isMeta(tableName) + ? metaRegionLocator.getRegionLocations(replicaId, reload) + : nonMetaRegionLocator.getRegionLocations(tableName, row, replicaId, type, reload); + internalAddListener(future, locsFuture, tableName, row, replicaId, type); + } else { + addListener(conn.getAdmin().getDescriptor(tableName), (tdesc, error) -> { + if (error != null) { + future.completeExceptionally(error); + return; + } + int regionReplicationCount = tdesc.getRegionReplication(); + if (replicaId >= regionReplicationCount) { + future + .completeExceptionally(new DoNotRetryIOException("The specified region replica id " + + replicaId + " does not exist, the REGION_REPLICATION of this table " + + tableName.getNameAsString() + " is " + regionReplicationCount + "," + + " this means that the maximum region replica id you can specify is " + + (regionReplicationCount - 1) + ".")); + return; + } + // meta region can not be split right now so we always call the same method. + // Change it later if the meta table can have more than one regions. + CompletableFuture locsFuture = isMeta(tableName) + ? metaRegionLocator.getRegionLocations(replicaId, reload) + : nonMetaRegionLocator.getRegionLocations(tableName, row, replicaId, type, reload); + internalAddListener(future, locsFuture, tableName, row, replicaId, type); + }); + } return withTimeout(future, timeoutNs, () -> "Timeout(" + TimeUnit.NANOSECONDS.toMillis(timeoutNs) + "ms) waiting for region location for " + tableName + ", row='" diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableRegionLocatorWithRegionReplicaId.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableRegionLocatorWithRegionReplicaId.java new file mode 100644 index 000000000000..2b82ef4a8d53 --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableRegionLocatorWithRegionReplicaId.java @@ -0,0 +1,174 @@ +/* + * 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.client; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import org.apache.hadoop.hbase.DoNotRetryIOException; +import org.apache.hadoop.hbase.HBaseClassTestRule; +import org.apache.hadoop.hbase.HBaseTestingUtil; +import org.apache.hadoop.hbase.HRegionLocation; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.regionserver.HRegion; +import org.apache.hadoop.hbase.testclassification.ClientTests; +import org.apache.hadoop.hbase.testclassification.MediumTests; +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.io.IOUtils; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; +import org.junit.rules.TestName; + +@Category({ MediumTests.class, ClientTests.class }) +public class TestAsyncTableRegionLocatorWithRegionReplicaId { + @ClassRule + public static final HBaseClassTestRule CLASS_RULE = + HBaseClassTestRule.forClass(TestAsyncTableRegionLocatorWithRegionReplicaId.class); + + @Rule + public TestName name = new TestName(); + + private ExpectedException exception = ExpectedException.none(); + + private final static HBaseTestingUtil UTIL = new HBaseTestingUtil(); + private static final String ROW = "r1"; + private static final byte[] FAMILY = Bytes.toBytes("info"); + private static final int REGION_REPLICATION_COUNT = 2; + // region replica id starts from 0 + private static final int NON_EXISTING_REGION_REPLICA_ID = REGION_REPLICATION_COUNT; + private static Connection connection; + private static AsyncConnection asyncConn; + private static Admin admin; + private TableName tableName; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + UTIL.startMiniCluster(1); + connection = UTIL.getConnection(); + asyncConn = ConnectionFactory.createAsyncConnection(UTIL.getConfiguration()).get(); + admin = UTIL.getAdmin(); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + IOUtils.cleanup(null, admin); + IOUtils.cleanup(null, connection); + UTIL.shutdownMiniCluster(); + } + + @Before + public void setUp() throws Exception { + tableName = TableName.valueOf(name.getMethodName()); + ColumnFamilyDescriptor columnFamilyDescriptor = + ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).build(); + TableDescriptor tableDescriptor = + TableDescriptorBuilder.newBuilder(tableName).setColumnFamily(columnFamilyDescriptor) + .setRegionReplication(REGION_REPLICATION_COUNT).build(); + admin.createTable(tableDescriptor); + UTIL.waitTableAvailable(tableName); + assertTrue(admin.tableExists(tableName)); + assertEquals(REGION_REPLICATION_COUNT, tableDescriptor.getRegionReplication()); + + List regions = UTIL.getHBaseCluster().getRegions(tableName); + assertEquals(REGION_REPLICATION_COUNT, regions.size()); + + Table table = connection.getTable(tableName); + Put put = new Put(Bytes.toBytes(ROW)).addColumn(FAMILY, Bytes.toBytes("q"), + Bytes.toBytes("test_value")); + table.put(put); + admin.flush(tableName); + + Scan scan = new Scan(); + ResultScanner rs = table.getScanner(scan); + rs.forEach(r -> assertEquals(ROW, Bytes.toString(r.getRow()))); + } + + @After + public void tearDown() throws Exception { + UTIL.deleteTable(tableName); + } + + @Test + public void testMetaTableRegionLocatorWithRegionReplicaId() + throws ExecutionException, InterruptedException { + AsyncTableRegionLocator locator = asyncConn.getRegionLocator(TableName.META_TABLE_NAME); + CompletableFuture future = + locator.getRegionLocation(tableName.getName(), RegionReplicaUtil.DEFAULT_REPLICA_ID, true); + HRegionLocation hrl = future.get(); + assertNotNull(hrl); + } + + @Test + public void testMetaTableRegionLocatorWithNonExistingRegionReplicaId() + throws InterruptedException { + AsyncTableRegionLocator locator = asyncConn.getRegionLocator(TableName.META_TABLE_NAME); + CompletableFuture future = + locator.getRegionLocation(tableName.getName(), NON_EXISTING_REGION_REPLICA_ID, true); + try { + future.get(); + } catch (ExecutionException e) { + assertTrue(e.getCause() instanceof DoNotRetryIOException); + String message = "The specified region replica id " + NON_EXISTING_REGION_REPLICA_ID + + " does not exist, the REGION_REPLICATION of this table " + + TableName.META_TABLE_NAME.getNameAsString() + " is " + + TableDescriptorBuilder.DEFAULT_REGION_REPLICATION + ", " + + "this means that the maximum region replica id you can specify is " + + (TableDescriptorBuilder.DEFAULT_REGION_REPLICATION - 1) + "."; + assertEquals(message, e.getCause().getMessage()); + } + } + + @Test + public void testTableRegionLocatorWithRegionReplicaId() + throws ExecutionException, InterruptedException { + AsyncTableRegionLocator locator = asyncConn.getRegionLocator(tableName); + CompletableFuture future = + locator.getRegionLocation(Bytes.toBytes(ROW), RegionReplicaUtil.DEFAULT_REPLICA_ID, true); + HRegionLocation hrl = future.get(); + assertNotNull(hrl); + } + + @Test + public void testTableRegionLocatorWithNonExistingRegionReplicaId() throws InterruptedException { + AsyncTableRegionLocator locator = asyncConn.getRegionLocator(tableName); + CompletableFuture future = + locator.getRegionLocation(Bytes.toBytes(ROW), NON_EXISTING_REGION_REPLICA_ID, true); + try { + future.get(); + } catch (ExecutionException e) { + assertTrue(e.getCause() instanceof DoNotRetryIOException); + String message = "The specified region replica id " + NON_EXISTING_REGION_REPLICA_ID + + " does not exist, the REGION_REPLICATION of this table " + tableName.getNameAsString() + + " is " + REGION_REPLICATION_COUNT + ", " + + "this means that the maximum region replica id you can specify is " + + (REGION_REPLICATION_COUNT - 1) + "."; + assertEquals(message, e.getCause().getMessage()); + } + } +} From 0a637ff02702e3254ab98ce33ddbc2b95f78201c Mon Sep 17 00:00:00 2001 From: guluo Date: Tue, 26 Mar 2024 22:15:39 +0800 Subject: [PATCH 2/3] Checking replica id on AsyncRpcRetryingCaller side --- .../hbase/client/AsyncRegionLocator.java | 80 ++++--------- .../hbase/client/AsyncRpcRetryingCaller.java | 23 ++++ .../AsyncSingleRequestRpcRetryingCaller.java | 4 + ...stScanOrGetWithReplicationFromClient.java} | 112 ++++++++++++------ 4 files changed, 124 insertions(+), 95 deletions(-) rename hbase-server/src/test/java/org/apache/hadoop/hbase/client/{TestAsyncTableRegionLocatorWithRegionReplicaId.java => TestScanOrGetWithReplicationFromClient.java} (57%) diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRegionLocator.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRegionLocator.java index e528e8b8f662..da58dd8e1e53 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRegionLocator.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRegionLocator.java @@ -35,7 +35,6 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; -import org.apache.hadoop.hbase.DoNotRetryIOException; import org.apache.hadoop.hbase.HRegionLocation; import org.apache.hadoop.hbase.RegionLocations; import org.apache.hadoop.hbase.ServerName; @@ -152,67 +151,36 @@ CompletableFuture getRegionLocations(TableName tableName, byte[ }, AsyncRegionLocator::getRegionNames, supplier); } - private void internalAddListener(CompletableFuture future, - CompletableFuture locsFuture, TableName tableName, byte[] row, int replicaId, - RegionLocateType type) { - addListener(locsFuture, (locs, error) -> { - if (error != null) { - future.completeExceptionally(error); - return; - } - HRegionLocation loc = locs.getRegionLocation(replicaId); - if (loc == null) { - future.completeExceptionally( - new RegionOfflineException("No location for " + tableName + ", row='" - + Bytes.toStringBinary(row) + "', locateType=" + type + ", replicaId=" + replicaId)); - } else if (loc.getServerName() == null) { - future - .completeExceptionally(new RegionOfflineException("No server address listed for region '" - + loc.getRegion().getRegionNameAsString() + ", row='" + Bytes.toStringBinary(row) - + "', locateType=" + type + ", replicaId=" + replicaId)); - } else { - future.complete(loc); - } - }); - } - CompletableFuture getRegionLocation(TableName tableName, byte[] row, int replicaId, RegionLocateType type, boolean reload, long timeoutNs) { final Supplier supplier = new TableSpanBuilder(conn) .setName("AsyncRegionLocator.getRegionLocation").setTableName(tableName); return tracedLocationFuture(() -> { + // meta region can not be split right now so we always call the same method. + // Change it later if the meta table can have more than one regions. CompletableFuture future = new CompletableFuture<>(); - if (replicaId == RegionReplicaUtil.DEFAULT_REPLICA_ID) { - // meta region can not be split right now so we always call the same method. - // Change it later if the meta table can have more than one regions. - CompletableFuture locsFuture = isMeta(tableName) - ? metaRegionLocator.getRegionLocations(replicaId, reload) - : nonMetaRegionLocator.getRegionLocations(tableName, row, replicaId, type, reload); - internalAddListener(future, locsFuture, tableName, row, replicaId, type); - } else { - addListener(conn.getAdmin().getDescriptor(tableName), (tdesc, error) -> { - if (error != null) { - future.completeExceptionally(error); - return; - } - int regionReplicationCount = tdesc.getRegionReplication(); - if (replicaId >= regionReplicationCount) { - future - .completeExceptionally(new DoNotRetryIOException("The specified region replica id " - + replicaId + " does not exist, the REGION_REPLICATION of this table " - + tableName.getNameAsString() + " is " + regionReplicationCount + "," - + " this means that the maximum region replica id you can specify is " - + (regionReplicationCount - 1) + ".")); - return; - } - // meta region can not be split right now so we always call the same method. - // Change it later if the meta table can have more than one regions. - CompletableFuture locsFuture = isMeta(tableName) - ? metaRegionLocator.getRegionLocations(replicaId, reload) - : nonMetaRegionLocator.getRegionLocations(tableName, row, replicaId, type, reload); - internalAddListener(future, locsFuture, tableName, row, replicaId, type); - }); - } + CompletableFuture locsFuture = isMeta(tableName) + ? metaRegionLocator.getRegionLocations(replicaId, reload) + : nonMetaRegionLocator.getRegionLocations(tableName, row, replicaId, type, reload); + addListener(locsFuture, (locs, error) -> { + if (error != null) { + future.completeExceptionally(error); + return; + } + HRegionLocation loc = locs.getRegionLocation(replicaId); + if (loc == null) { + future.completeExceptionally( + new RegionOfflineException("No location for " + tableName + ", row='" + + Bytes.toStringBinary(row) + "', locateType=" + type + ", replicaId=" + replicaId)); + } else if (loc.getServerName() == null) { + future.completeExceptionally( + new RegionOfflineException("No server address listed for region '" + + loc.getRegion().getRegionNameAsString() + ", row='" + Bytes.toStringBinary(row) + + "', locateType=" + type + ", replicaId=" + replicaId)); + } else { + future.complete(loc); + } + }); return withTimeout(future, timeoutNs, () -> "Timeout(" + TimeUnit.NANOSECONDS.toMillis(timeoutNs) + "ms) waiting for region location for " + tableName + ", row='" diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRpcRetryingCaller.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRpcRetryingCaller.java index 32da6eedd10f..5a33b75397f1 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRpcRetryingCaller.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRpcRetryingCaller.java @@ -204,6 +204,29 @@ protected final void onError(Throwable t, Supplier errMsg, } if (disabled) { future.completeExceptionally(new TableNotEnabledException(tableName.get())); + return; + } + if (this instanceof AsyncSingleRequestRpcRetryingCaller) { + AsyncSingleRequestRpcRetryingCaller caller = (AsyncSingleRequestRpcRetryingCaller) this; + int replicaId = caller.getReplicaId(); + FutureUtils.addListener(conn.getAdmin().getDescriptor(tableName.get()), + (tdesc, tdescError) -> { + if (tdescError != null) { + future.completeExceptionally(tdescError); + return; + } + int regionReplicationCount = tdesc.getRegionReplication(); + if (replicaId >= regionReplicationCount) { + future.completeExceptionally( + new DoNotRetryIOException("The specified region replica id " + replicaId + + " does not exist, the REGION_REPLICATION of this table " + + tableName.get().getNameAsString() + " is " + regionReplicationCount + "," + + " this means that the maximum region replica id you can specify is " + + (regionReplicationCount - 1) + ".")); + return; + } + tryScheduleRetry(error); + }); } else { tryScheduleRetry(error); } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncSingleRequestRpcRetryingCaller.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncSingleRequestRpcRetryingCaller.java index a0d536aef5f7..b25c62e8a3c9 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncSingleRequestRpcRetryingCaller.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncSingleRequestRpcRetryingCaller.java @@ -122,4 +122,8 @@ protected void doCall() { protected Optional getTableName() { return Optional.of(tableName); } + + public int getReplicaId() { + return replicaId; + } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableRegionLocatorWithRegionReplicaId.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestScanOrGetWithReplicationFromClient.java similarity index 57% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableRegionLocatorWithRegionReplicaId.java rename to hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestScanOrGetWithReplicationFromClient.java index 2b82ef4a8d53..850026d9a904 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableRegionLocatorWithRegionReplicaId.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestScanOrGetWithReplicationFromClient.java @@ -18,17 +18,15 @@ package org.apache.hadoop.hbase.client; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.io.IOException; import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import org.apache.hadoop.hbase.DoNotRetryIOException; import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.HBaseTestingUtil; -import org.apache.hadoop.hbase.HRegionLocation; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.filter.PrefixFilter; import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.testclassification.ClientTests; import org.apache.hadoop.hbase.testclassification.MediumTests; @@ -46,10 +44,10 @@ import org.junit.rules.TestName; @Category({ MediumTests.class, ClientTests.class }) -public class TestAsyncTableRegionLocatorWithRegionReplicaId { +public class TestScanOrGetWithReplicationFromClient { @ClassRule public static final HBaseClassTestRule CLASS_RULE = - HBaseClassTestRule.forClass(TestAsyncTableRegionLocatorWithRegionReplicaId.class); + HBaseClassTestRule.forClass(TestScanOrGetWithReplicationFromClient.class); @Rule public TestName name = new TestName(); @@ -63,7 +61,6 @@ public class TestAsyncTableRegionLocatorWithRegionReplicaId { // region replica id starts from 0 private static final int NON_EXISTING_REGION_REPLICA_ID = REGION_REPLICATION_COUNT; private static Connection connection; - private static AsyncConnection asyncConn; private static Admin admin; private TableName tableName; @@ -71,7 +68,6 @@ public class TestAsyncTableRegionLocatorWithRegionReplicaId { public static void setUpBeforeClass() throws Exception { UTIL.startMiniCluster(1); connection = UTIL.getConnection(); - asyncConn = ConnectionFactory.createAsyncConnection(UTIL.getConfiguration()).get(); admin = UTIL.getAdmin(); } @@ -115,60 +111,98 @@ public void tearDown() throws Exception { } @Test - public void testMetaTableRegionLocatorWithRegionReplicaId() - throws ExecutionException, InterruptedException { - AsyncTableRegionLocator locator = asyncConn.getRegionLocator(TableName.META_TABLE_NAME); - CompletableFuture future = - locator.getRegionLocation(tableName.getName(), RegionReplicaUtil.DEFAULT_REPLICA_ID, true); - HRegionLocation hrl = future.get(); - assertNotNull(hrl); + public void testScanMetaWithRegionReplicaId() throws IOException { + Table metaTable = connection.getTable(TableName.META_TABLE_NAME); + Scan scan = new Scan(); + scan.setFilter(new PrefixFilter(tableName.getName())); + scan.setReplicaId(RegionReplicaUtil.DEFAULT_REPLICA_ID); + scan.setConsistency(Consistency.TIMELINE); + ResultScanner rs = metaTable.getScanner(scan); + rs.forEach(r -> assertTrue(Bytes.toString(r.getRow()).contains(tableName.getNameAsString()))); } @Test - public void testMetaTableRegionLocatorWithNonExistingRegionReplicaId() - throws InterruptedException { - AsyncTableRegionLocator locator = asyncConn.getRegionLocator(TableName.META_TABLE_NAME); - CompletableFuture future = - locator.getRegionLocation(tableName.getName(), NON_EXISTING_REGION_REPLICA_ID, true); + public void testScanMetaWithNonExistingRegionReplicaId() throws IOException { + Table metaTable = connection.getTable(TableName.META_TABLE_NAME); + Scan scan = new Scan(); + scan.setReplicaId(NON_EXISTING_REGION_REPLICA_ID); + scan.setConsistency(Consistency.TIMELINE); + exception.expect(DoNotRetryIOException.class); + ResultScanner rs = metaTable.getScanner(scan); try { - future.get(); - } catch (ExecutionException e) { - assertTrue(e.getCause() instanceof DoNotRetryIOException); + rs.forEach(r -> Bytes.toString(r.getRow())); + } catch (Exception e) { + Throwable throwable = e.getCause(); + assertTrue(throwable instanceof DoNotRetryIOException); String message = "The specified region replica id " + NON_EXISTING_REGION_REPLICA_ID + " does not exist, the REGION_REPLICATION of this table " + TableName.META_TABLE_NAME.getNameAsString() + " is " + TableDescriptorBuilder.DEFAULT_REGION_REPLICATION + ", " + "this means that the maximum region replica id you can specify is " + (TableDescriptorBuilder.DEFAULT_REGION_REPLICATION - 1) + "."; - assertEquals(message, e.getCause().getMessage()); + assertEquals(message, throwable.getMessage()); + } + } + + @Test + public void testScanTableWithRegionReplicaId() throws IOException { + Table table = connection.getTable(tableName); + Scan scan = new Scan(); + scan.setReplicaId(RegionReplicaUtil.DEFAULT_REPLICA_ID); + scan.setConsistency(Consistency.TIMELINE); + ResultScanner rs = table.getScanner(scan); + rs.forEach(r -> assertEquals(ROW, Bytes.toString(r.getRow()))); + } + + @Test + public void testScanTableWithNonExistingRegionReplicaId() throws IOException { + Table table = connection.getTable(tableName); + Scan scan = new Scan(); + scan.setReplicaId(NON_EXISTING_REGION_REPLICA_ID); + scan.setConsistency(Consistency.TIMELINE); + exception.expect(DoNotRetryIOException.class); + ResultScanner rs = table.getScanner(scan); + try { + rs.forEach(r -> Bytes.toString(r.getRow())); + } catch (Exception e) { + Throwable throwable = e.getCause(); + assertTrue(throwable instanceof DoNotRetryIOException); + String message = "The specified region replica id " + NON_EXISTING_REGION_REPLICA_ID + + " does not exist, the REGION_REPLICATION of this table " + tableName.getNameAsString() + + " is " + REGION_REPLICATION_COUNT + ", " + + "this means that the maximum region replica id you can specify is " + + (REGION_REPLICATION_COUNT - 1) + "."; + assertEquals(message, throwable.getMessage()); } } @Test - public void testTableRegionLocatorWithRegionReplicaId() - throws ExecutionException, InterruptedException { - AsyncTableRegionLocator locator = asyncConn.getRegionLocator(tableName); - CompletableFuture future = - locator.getRegionLocation(Bytes.toBytes(ROW), RegionReplicaUtil.DEFAULT_REPLICA_ID, true); - HRegionLocation hrl = future.get(); - assertNotNull(hrl); + public void testGetTableWithRegionReplicaId() throws IOException { + Table table = connection.getTable(tableName); + Get get = new Get(Bytes.toBytes(ROW)).setConsistency(Consistency.TIMELINE) + .setReplicaId(RegionReplicaUtil.DEFAULT_REPLICA_ID); + Result result = table.get(get); + assertEquals(ROW, Bytes.toString(result.getRow())); + String value = Bytes.toString(result.getValue(FAMILY, Bytes.toBytes("q"))); + assertEquals("test_value", value); } @Test - public void testTableRegionLocatorWithNonExistingRegionReplicaId() throws InterruptedException { - AsyncTableRegionLocator locator = asyncConn.getRegionLocator(tableName); - CompletableFuture future = - locator.getRegionLocation(Bytes.toBytes(ROW), NON_EXISTING_REGION_REPLICA_ID, true); + public void testGetTableWithNonExistingRegionReplicaId() throws IOException { + Table table = connection.getTable(tableName); + Get get = new Get(Bytes.toBytes(ROW)).setConsistency(Consistency.TIMELINE) + .setReplicaId(NON_EXISTING_REGION_REPLICA_ID); try { - future.get(); - } catch (ExecutionException e) { - assertTrue(e.getCause() instanceof DoNotRetryIOException); + Result result = table.get(get); + result.getValue(FAMILY, Bytes.toBytes("q")); + } catch (Exception e) { + assertTrue(e instanceof DoNotRetryIOException); String message = "The specified region replica id " + NON_EXISTING_REGION_REPLICA_ID + " does not exist, the REGION_REPLICATION of this table " + tableName.getNameAsString() + " is " + REGION_REPLICATION_COUNT + ", " + "this means that the maximum region replica id you can specify is " + (REGION_REPLICATION_COUNT - 1) + "."; - assertEquals(message, e.getCause().getMessage()); + assertEquals(message, e.getMessage()); } } } From 909a76656c2c2d5cb02282a84c7b63014af97aad Mon Sep 17 00:00:00 2001 From: guluo Date: Sat, 25 May 2024 22:48:31 +0800 Subject: [PATCH 3/3] Update test units --- .../client/TestScanOrGetWithReplicationFromClient.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestScanOrGetWithReplicationFromClient.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestScanOrGetWithReplicationFromClient.java index 850026d9a904..d02a2ae23462 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestScanOrGetWithReplicationFromClient.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestScanOrGetWithReplicationFromClient.java @@ -19,6 +19,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.IOException; import java.util.List; @@ -40,7 +41,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; -import org.junit.rules.ExpectedException; import org.junit.rules.TestName; @Category({ MediumTests.class, ClientTests.class }) @@ -52,8 +52,6 @@ public class TestScanOrGetWithReplicationFromClient { @Rule public TestName name = new TestName(); - private ExpectedException exception = ExpectedException.none(); - private final static HBaseTestingUtil UTIL = new HBaseTestingUtil(); private static final String ROW = "r1"; private static final byte[] FAMILY = Bytes.toBytes("info"); @@ -127,10 +125,10 @@ public void testScanMetaWithNonExistingRegionReplicaId() throws IOException { Scan scan = new Scan(); scan.setReplicaId(NON_EXISTING_REGION_REPLICA_ID); scan.setConsistency(Consistency.TIMELINE); - exception.expect(DoNotRetryIOException.class); ResultScanner rs = metaTable.getScanner(scan); try { rs.forEach(r -> Bytes.toString(r.getRow())); + fail("Should not reach here"); } catch (Exception e) { Throwable throwable = e.getCause(); assertTrue(throwable instanceof DoNotRetryIOException); @@ -160,10 +158,10 @@ public void testScanTableWithNonExistingRegionReplicaId() throws IOException { Scan scan = new Scan(); scan.setReplicaId(NON_EXISTING_REGION_REPLICA_ID); scan.setConsistency(Consistency.TIMELINE); - exception.expect(DoNotRetryIOException.class); ResultScanner rs = table.getScanner(scan); try { rs.forEach(r -> Bytes.toString(r.getRow())); + fail("Should not reach here"); } catch (Exception e) { Throwable throwable = e.getCause(); assertTrue(throwable instanceof DoNotRetryIOException); @@ -195,6 +193,7 @@ public void testGetTableWithNonExistingRegionReplicaId() throws IOException { try { Result result = table.get(get); result.getValue(FAMILY, Bytes.toBytes("q")); + fail("Should not reach here"); } catch (Exception e) { assertTrue(e instanceof DoNotRetryIOException); String message = "The specified region replica id " + NON_EXISTING_REGION_REPLICA_ID