From e808ea1d045eecc07131d3f3d0fd7db1b06db4be Mon Sep 17 00:00:00 2001 From: binlijin Date: Thu, 31 Oct 2019 04:28:01 +0800 Subject: [PATCH] HBASE-22739 ArrayIndexOutOfBoundsException when balance (#729) Signed-off-by: stack --- .../hadoop/hbase/master/balancer/BaseLoadBalancer.java | 5 ++++- .../hbase/master/balancer/TestBaseLoadBalancer.java | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java index 1fa2bcda4ad..5f1e0f91827 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java @@ -142,6 +142,7 @@ public abstract class BaseLoadBalancer implements LoadBalancer { int[] serverIndexToRackIndex; //serverIndex -> rack index int[][] regionsPerServer; //serverIndex -> region list + int[] serverIndexToRegionsOffset; //serverIndex -> offset of region list int[][] regionsPerHost; //hostIndex -> list of regions int[][] regionsPerRack; //rackIndex -> region list int[][] primariesOfRegionsPerServer; //serverIndex -> sorted list of regions by primary region index @@ -276,6 +277,7 @@ public abstract class BaseLoadBalancer implements LoadBalancer { serverIndexToHostIndex = new int[numServers]; serverIndexToRackIndex = new int[numServers]; regionsPerServer = new int[numServers][]; + serverIndexToRegionsOffset = new int[numServers]; regionsPerHost = new int[numHosts][]; regionsPerRack = new int[numRacks][]; primariesOfRegionsPerServer = new int[numServers][]; @@ -321,7 +323,7 @@ public abstract class BaseLoadBalancer implements LoadBalancer { for (Entry> entry : clusterState.entrySet()) { int serverIndex = serversToIndex.get(entry.getKey().getHostAndPort()); - regionPerServerIndex = 0; + regionPerServerIndex = serverIndexToRegionsOffset[serverIndex]; int hostIndex = hostsToIndex.get(entry.getKey().getHostname()); serverIndexToHostIndex[serverIndex] = hostIndex; @@ -334,6 +336,7 @@ public abstract class BaseLoadBalancer implements LoadBalancer { regionsPerServer[serverIndex][regionPerServerIndex++] = regionIndex; regionIndex++; } + serverIndexToRegionsOffset[serverIndex] = regionPerServerIndex; } for (RegionInfo region : unassignedRegions) { diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBaseLoadBalancer.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBaseLoadBalancer.java index 041167984e7..0acfe42cfdc 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBaseLoadBalancer.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBaseLoadBalancer.java @@ -473,7 +473,7 @@ public class TestBaseLoadBalancer extends BalancerTestBase { // sharing same host and port List servers = getListOfServerNames(randomServers(10, 10)); List regions = randomRegions(101); - Map> clusterState = new HashMap<>(); + Map> clusterState = new TreeMap<>(); assignRegions(regions, servers, clusterState); @@ -491,6 +491,13 @@ public class TestBaseLoadBalancer extends BalancerTestBase { BaseLoadBalancer.Cluster cluster = new Cluster(clusterState, null, null, null); assertEquals(101 + 9, cluster.numRegions); assertEquals(10, cluster.numServers); // only 10 servers because they share the same host + port + + // test move + ServerName sn = oldServers.get(0); + int r0 = ArrayUtils.indexOf(cluster.regions, clusterState.get(sn).get(0)); + int f0 = cluster.serversToIndex.get(sn.getHostAndPort()); + int t0 = cluster.serversToIndex.get(servers.get(1).getHostAndPort()); + cluster.doAction(new MoveRegionAction(r0, f0, t0)); } private void assignRegions(List regions, List servers,