From e1afc5932a0f0f32e5a83e48ad6af5c85780c0bf Mon Sep 17 00:00:00 2001 From: Toshihiro Suzuki Date: Mon, 26 Mar 2018 15:03:45 -0700 Subject: [PATCH] HBASE-20229 ConnectionImplementation.locateRegions() returns duplicated entries when region replication is on --- .../client/ConnectionImplementation.java | 3 ++ .../client/TestConnectionImplementation.java | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java index 6408044c391..77231616074 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java @@ -672,6 +672,9 @@ class ConnectionImplementation implements ClusterConnection, Closeable { } List locations = new ArrayList<>(); for (RegionInfo regionInfo : regions) { + if (!RegionReplicaUtil.isDefaultReplica(regionInfo)) { + continue; + } RegionLocations list = locateRegion(tableName, regionInfo.getStartKey(), useCache, true); if (list != null) { for (HRegionLocation loc : list.getRegionLocations()) { diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestConnectionImplementation.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestConnectionImplementation.java index 521317d404e..4d9f39bebe0 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestConnectionImplementation.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestConnectionImplementation.java @@ -29,6 +29,7 @@ import java.lang.reflect.Modifier; import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadLocalRandom; @@ -37,6 +38,9 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.HBaseClassTestRule; @@ -1044,4 +1048,36 @@ public class TestConnectionImplementation { table.close(); connection.close(); } + + @Test + public void testLocateRegionsWithRegionReplicas() throws IOException { + int regionReplication = 3; + byte[] family = Bytes.toBytes("cf"); + TableName tableName = TableName.valueOf(name.getMethodName()); + + // Create a table with region replicas + TableDescriptorBuilder builder = TableDescriptorBuilder + .newBuilder(tableName) + .setRegionReplication(regionReplication) + .setColumnFamily(ColumnFamilyDescriptorBuilder.of(family)); + TEST_UTIL.getAdmin().createTable(builder.build()); + + try (ConnectionImplementation con = (ConnectionImplementation) ConnectionFactory. + createConnection(TEST_UTIL.getConfiguration())) { + // Get locations of the regions of the table + List locations = con.locateRegions(tableName, false, false); + + // The size of the returned locations should be 3 + assertEquals(regionReplication, locations.size()); + + // The replicaIds of the returned locations should be 0, 1 and 2 + Set expectedReplicaIds = IntStream.range(0, regionReplication). + boxed().collect(Collectors.toSet()); + for (HRegionLocation location : locations) { + assertTrue(expectedReplicaIds.remove(location.getRegion().getReplicaId())); + } + } finally { + TEST_UTIL.deleteTable(tableName); + } + } }