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 785f6d51f5f..8f5b6f56f2c 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 @@ -805,6 +805,7 @@ public abstract class BaseLoadBalancer implements LoadBalancer { } else if (oldServer >= 0 && (numRegionsPerServerPerTable[oldServer][tableIndex] + 1) == numMaxRegionsPerTable[tableIndex]) { //recompute maxRegionsPerTable since the previous value was coming from the old server + numMaxRegionsPerTable[tableIndex] = 0; for (int serverIndex = 0 ; serverIndex < numRegionsPerServerPerTable.length; serverIndex++) { if (numRegionsPerServerPerTable[serverIndex][tableIndex] > numMaxRegionsPerTable[tableIndex]) { numMaxRegionsPerTable[tableIndex] = numRegionsPerServerPerTable[serverIndex][tableIndex]; diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java index ebd86be8fcf..56c2a24464d 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java @@ -17,6 +17,7 @@ */ package org.apache.hadoop.hbase.master.balancer; +import com.google.common.annotations.VisibleForTesting; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; @@ -318,6 +319,12 @@ public class StochasticLoadBalancer extends BaseLoadBalancer { return balanceCluster(clusterState); } + @VisibleForTesting + Cluster.Action nextAction(Cluster cluster) { + return candidateGenerators.get(RANDOM.nextInt(candidateGenerators.size())) + .generate(cluster); + } + /** * Given the cluster state this will try and approach an optimal balance. This * should always approach the optimal state given enough steps. @@ -384,9 +391,7 @@ public class StochasticLoadBalancer extends BaseLoadBalancer { long step; for (step = 0; step < computedMaxSteps; step++) { - int generatorIdx = RANDOM.nextInt(candidateGenerators.size()); - CandidateGenerator p = candidateGenerators.get(generatorIdx); - Cluster.Action action = p.generate(cluster); + Cluster.Action action = nextAction(cluster); if (action.type == Type.NULL) { continue; diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java index 1dc161156dd..b97567ddc3d 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java @@ -280,6 +280,27 @@ public class TestStochasticLoadBalancer extends BalancerTestBase { assertEquals(1, costFunction.cost(), 0.01); } + @Test + public void testCostAfterUndoAction() { + final int runs = 10; + loadBalancer.setConf(conf); + for (int[] mockCluster : clusterStateMocks) { + BaseLoadBalancer.Cluster cluster = mockCluster(mockCluster); + loadBalancer.initCosts(cluster); + for (int i = 0; i != runs; ++i) { + final double expectedCost = loadBalancer.computeCost(cluster, Double.MAX_VALUE); + Cluster.Action action = loadBalancer.nextAction(cluster); + cluster.doAction(action); + loadBalancer.updateCostsWithAction(cluster, action); + Cluster.Action undoAction = action.undoAction(); + cluster.doAction(undoAction); + loadBalancer.updateCostsWithAction(cluster, undoAction); + final double actualCost = loadBalancer.computeCost(cluster, Double.MAX_VALUE); + assertEquals(expectedCost, actualCost, 0); + } + } + } + @Test public void testTableSkewCost() { Configuration conf = HBaseConfiguration.create();