4848import org .apache .hadoop .hbase .testclassification .MediumTests ;
4949import org .apache .hadoop .hbase .util .Bytes ;
5050import org .apache .hadoop .hbase .util .EnvironmentEdgeManager ;
51+ import org .junit .Before ;
52+ import org .junit .BeforeClass ;
5153import org .junit .ClassRule ;
5254import org .junit .Test ;
5355import org .junit .experimental .categories .Category ;
@@ -65,6 +67,18 @@ public class TestStochasticLoadBalancer extends BalancerTestBase {
6567
6668 // Mapping of locality test -> expected locality
6769 private float [] expectedLocalities = { 1.0f , 0.0f , 0.50f , 0.25f , 1.0f };
70+ private static Configuration storedConfiguration ;
71+
72+ @ BeforeClass
73+ public static void saveInitialConfiguration () {
74+ storedConfiguration = new Configuration (conf );
75+ }
76+
77+ @ Before
78+ public void beforeEachTest () {
79+ conf = new Configuration (storedConfiguration );
80+ loadBalancer .onConfigurationChange (conf );
81+ }
6882
6983 /**
7084 * Data set for testLocalityCost: [test][0][0] = mapping of server to number of regions it hosts
@@ -160,142 +174,107 @@ public void testUpdateBalancerLoadInfo() {
160174 BalancerClusterState clusterState = mockCluster (cluster );
161175 Map <TableName , Map <ServerName , List <RegionInfo >>> LoadOfAllTable =
162176 (Map ) mockClusterServersWithTables (servers );
163- try {
164- boolean [] perTableBalancerConfigs = { true , false };
165- for (boolean isByTable : perTableBalancerConfigs ) {
166- conf .setBoolean (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE , isByTable );
167- loadBalancer .onConfigurationChange (conf );
168- dummyMetricsStochasticBalancer .clearDummyMetrics ();
169- loadBalancer .updateBalancerLoadInfo (LoadOfAllTable );
170- assertTrue ("Metrics should be recorded!" ,
171- dummyMetricsStochasticBalancer .getDummyCostsMap () != null
172- && !dummyMetricsStochasticBalancer .getDummyCostsMap ().isEmpty ());
173-
174- String metricRecordKey ;
175- if (isByTable ) {
176- metricRecordKey = "table1#" + StochasticLoadBalancer .OVERALL_COST_FUNCTION_NAME ;
177- } else {
178- metricRecordKey = HConstants .ENSEMBLE_TABLE_NAME + "#"
179- + StochasticLoadBalancer .OVERALL_COST_FUNCTION_NAME ;
180- }
181- double curOverallCost = loadBalancer .computeCost (clusterState , Double .MAX_VALUE );
182- double curOverallCostInMetrics =
183- dummyMetricsStochasticBalancer .getDummyCostsMap ().get (metricRecordKey );
184- assertEquals (curOverallCost , curOverallCostInMetrics , 0.001 );
185- }
186- } finally {
187- conf .unset (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE );
177+ boolean [] perTableBalancerConfigs = { true , false };
178+ for (boolean isByTable : perTableBalancerConfigs ) {
179+ conf .setBoolean (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE , isByTable );
188180 loadBalancer .onConfigurationChange (conf );
181+ dummyMetricsStochasticBalancer .clearDummyMetrics ();
182+ loadBalancer .updateBalancerLoadInfo (LoadOfAllTable );
183+ assertTrue ("Metrics should be recorded!" ,
184+ dummyMetricsStochasticBalancer .getDummyCostsMap () != null
185+ && !dummyMetricsStochasticBalancer .getDummyCostsMap ().isEmpty ());
186+
187+ String metricRecordKey ;
188+ if (isByTable ) {
189+ metricRecordKey = "table1#" + StochasticLoadBalancer .OVERALL_COST_FUNCTION_NAME ;
190+ } else {
191+ metricRecordKey =
192+ HConstants .ENSEMBLE_TABLE_NAME + "#" + StochasticLoadBalancer .OVERALL_COST_FUNCTION_NAME ;
193+ }
194+ double curOverallCost = loadBalancer .computeCost (clusterState , Double .MAX_VALUE );
195+ double curOverallCostInMetrics =
196+ dummyMetricsStochasticBalancer .getDummyCostsMap ().get (metricRecordKey );
197+ assertEquals (curOverallCost , curOverallCostInMetrics , 0.001 );
189198 }
190199 }
191200
192201 @ Test
193202 public void testUpdateStochasticCosts () {
194- float minCost = conf .getFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 0.05f );
195- try {
196- int [] cluster = new int [] { 10 , 0 };
197- Map <ServerName , List <RegionInfo >> servers = mockClusterServers (cluster );
198- BalancerClusterState clusterState = mockCluster (cluster );
199- conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 1.0f );
200- conf .setBoolean (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE , false );
201- loadBalancer .onConfigurationChange (conf );
202- dummyMetricsStochasticBalancer .clearDummyMetrics ();
203- List <RegionPlan > plans =
204- loadBalancer .balanceCluster ((Map ) mockClusterServersWithTables (servers ));
205-
206- assertTrue ("Balance plan should not be empty!" , plans != null && !plans .isEmpty ());
207- assertTrue ("There should be metrics record in MetricsStochasticBalancer" ,
208- !dummyMetricsStochasticBalancer .getDummyCostsMap ().isEmpty ());
209-
210- double overallCostOfCluster = loadBalancer .computeCost (clusterState , Double .MAX_VALUE );
211- double overallCostInMetrics = dummyMetricsStochasticBalancer .getDummyCostsMap ().get (
212- HConstants .ENSEMBLE_TABLE_NAME + "#" + StochasticLoadBalancer .OVERALL_COST_FUNCTION_NAME );
213- assertEquals (overallCostOfCluster , overallCostInMetrics , 0.001 );
214- } finally {
215- // reset config
216- conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , minCost );
217- conf .unset (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE );
218- loadBalancer .onConfigurationChange (conf );
219- }
203+ int [] cluster = new int [] { 10 , 0 };
204+ Map <ServerName , List <RegionInfo >> servers = mockClusterServers (cluster );
205+ BalancerClusterState clusterState = mockCluster (cluster );
206+ conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 1.0f );
207+ conf .setBoolean (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE , false );
208+ loadBalancer .onConfigurationChange (conf );
209+ dummyMetricsStochasticBalancer .clearDummyMetrics ();
210+ List <RegionPlan > plans =
211+ loadBalancer .balanceCluster ((Map ) mockClusterServersWithTables (servers ));
212+
213+ assertTrue ("Balance plan should not be empty!" , plans != null && !plans .isEmpty ());
214+ assertTrue ("There should be metrics record in MetricsStochasticBalancer" ,
215+ !dummyMetricsStochasticBalancer .getDummyCostsMap ().isEmpty ());
216+
217+ double overallCostOfCluster = loadBalancer .computeCost (clusterState , Double .MAX_VALUE );
218+ double overallCostInMetrics = dummyMetricsStochasticBalancer .getDummyCostsMap ().get (
219+ HConstants .ENSEMBLE_TABLE_NAME + "#" + StochasticLoadBalancer .OVERALL_COST_FUNCTION_NAME );
220+ assertEquals (overallCostOfCluster , overallCostInMetrics , 0.001 );
220221 }
221222
222223 @ Test
223224 public void testUpdateStochasticCostsIfBalanceNotRan () {
224- float minCost = conf .getFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 0.05f );
225- try {
226- int [] cluster = new int [] { 10 , 10 };
227- Map <ServerName , List <RegionInfo >> servers = mockClusterServers (cluster );
228- BalancerClusterState clusterState = mockCluster (cluster );
229- conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , Float .MAX_VALUE );
230- conf .setBoolean (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE , false );
231- loadBalancer .onConfigurationChange (conf );
232- dummyMetricsStochasticBalancer .clearDummyMetrics ();
233- List <RegionPlan > plans =
234- loadBalancer .balanceCluster ((Map ) mockClusterServersWithTables (servers ));
235-
236- assertTrue ("Balance plan should be empty!" , plans == null || plans .isEmpty ());
237- assertTrue ("There should be metrics record in MetricsStochasticBalancer!" ,
238- !dummyMetricsStochasticBalancer .getDummyCostsMap ().isEmpty ());
239-
240- double overallCostOfCluster = loadBalancer .computeCost (clusterState , Double .MAX_VALUE );
241- double overallCostInMetrics = dummyMetricsStochasticBalancer .getDummyCostsMap ().get (
242- HConstants .ENSEMBLE_TABLE_NAME + "#" + StochasticLoadBalancer .OVERALL_COST_FUNCTION_NAME );
243- assertEquals (overallCostOfCluster , overallCostInMetrics , 0.001 );
244- } finally {
245- // reset config
246- conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , minCost );
247- conf .unset (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE );
248- loadBalancer .onConfigurationChange (conf );
249- }
225+ int [] cluster = new int [] { 10 , 10 };
226+ Map <ServerName , List <RegionInfo >> servers = mockClusterServers (cluster );
227+ BalancerClusterState clusterState = mockCluster (cluster );
228+ conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , Float .MAX_VALUE );
229+ conf .setBoolean (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE , false );
230+ loadBalancer .onConfigurationChange (conf );
231+ dummyMetricsStochasticBalancer .clearDummyMetrics ();
232+ List <RegionPlan > plans =
233+ loadBalancer .balanceCluster ((Map ) mockClusterServersWithTables (servers ));
234+
235+ assertTrue ("Balance plan should be empty!" , plans == null || plans .isEmpty ());
236+ assertTrue ("There should be metrics record in MetricsStochasticBalancer!" ,
237+ !dummyMetricsStochasticBalancer .getDummyCostsMap ().isEmpty ());
238+
239+ double overallCostOfCluster = loadBalancer .computeCost (clusterState , Double .MAX_VALUE );
240+ double overallCostInMetrics = dummyMetricsStochasticBalancer .getDummyCostsMap ().get (
241+ HConstants .ENSEMBLE_TABLE_NAME + "#" + StochasticLoadBalancer .OVERALL_COST_FUNCTION_NAME );
242+ assertEquals (overallCostOfCluster , overallCostInMetrics , 0.001 );
250243 }
251244
252245 @ Test
253246 public void testNeedBalance () {
254- float minCost = conf .getFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 0.05f );
255- float slop = conf .getFloat (HConstants .LOAD_BALANCER_SLOP_KEY , 0.2f );
256247 conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 1.0f );
257248 conf .setFloat (HConstants .LOAD_BALANCER_SLOP_KEY , -1f );
258- try {
259- // Test with/without per table balancer.
260- boolean [] perTableBalancerConfigs = { true , false };
261- for (boolean isByTable : perTableBalancerConfigs ) {
262- conf .setBoolean (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE , isByTable );
263- loadBalancer .onConfigurationChange (conf );
264-
265- for (int [] mockCluster : clusterStateMocks ) {
266- assertTrue (hasEmptyBalancerPlans (mockCluster ) || needsBalanceIdleRegion (mockCluster ));
267- }
268- }
269- } finally {
270- // reset config
271- conf .unset (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE );
272- conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , minCost );
273- conf .setFloat (HConstants .LOAD_BALANCER_SLOP_KEY , slop );
249+ conf .setBoolean ("hbase.master.balancer.stochastic.runMaxSteps" , false );
250+ conf .setLong ("hbase.master.balancer.stochastic.maxSteps" , 5000L );
251+ // Test with/without per table balancer.
252+ boolean [] perTableBalancerConfigs = { true , false };
253+ for (boolean isByTable : perTableBalancerConfigs ) {
254+ conf .setBoolean (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE , isByTable );
274255 loadBalancer .onConfigurationChange (conf );
256+ for (int [] mockCluster : clusterStateMocks ) {
257+ assertTrue (hasEmptyBalancerPlans (mockCluster ) || needsBalanceIdleRegion (mockCluster ));
258+ }
275259 }
276260 }
277261
278262 @ Test
279263 public void testBalanceOfSloppyServers () {
280- float minCost = conf .getFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 0.025f );
281- try {
282- // We are testing slop checks, so don't "accidentally" balance due to a minCost calculation.
283- // During development, imbalance of a 100 server cluster, with one node having 10 regions
284- // and the rest having 5, is 0.0048. With minCostNeedBalance default of 0.025, test should
285- // validate slop checks without this override. We override just to ensure we will always
286- // validate slop check here, and for small clusters as well.
287- conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 1.0f );
288- loadBalancer .onConfigurationChange (conf );
289- for (int [] mockCluster : clusterStateMocksWithNoSlop ) {
290- assertTrue (hasEmptyBalancerPlans (mockCluster ));
291- }
292- for (int [] mockCluster : clusterStateMocksWithSlop ) {
293- assertFalse (hasEmptyBalancerPlans (mockCluster ));
294- }
295- } finally {
296- // reset config
297- conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , minCost );
298- loadBalancer .onConfigurationChange (conf );
264+ // We are testing slop checks, so don't "accidentally" balance due to a minCost calculation.
265+ // During development, imbalance of a 100 server cluster, with one node having 10 regions
266+ // and the rest having 5, is 0.0048. With minCostNeedBalance default of 0.025, test should
267+ // validate slop checks without this override. We override just to ensure we will always
268+ // validate slop check here, and for small clusters as well.
269+ conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 1.0f );
270+ conf .setBoolean ("hbase.master.balancer.stochastic.runMaxSteps" , false );
271+ conf .setLong ("hbase.master.balancer.stochastic.maxSteps" , 5000L );
272+ loadBalancer .onConfigurationChange (conf );
273+ for (int [] mockCluster : clusterStateMocksWithNoSlop ) {
274+ assertTrue (hasEmptyBalancerPlans (mockCluster ));
275+ }
276+ for (int [] mockCluster : clusterStateMocksWithSlop ) {
277+ assertFalse (hasEmptyBalancerPlans (mockCluster ));
299278 }
300279 }
301280
@@ -306,17 +285,12 @@ public void testSloppyTablesLoadBalanceByTable() {
306285 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 },
307286 new int [] { 2 , 8 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
308287 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 }, };
309- float minCost = conf .getFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 0.025f );
310- try {
311- conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 1.0f );
312- conf .setBoolean (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE , true );
313- loadBalancer .onConfigurationChange (conf );
314- assertFalse (hasEmptyBalancerPlans (regionsPerServerPerTable ));
315- } finally {
316- conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , minCost );
317- conf .unset (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE );
318- loadBalancer .onConfigurationChange (conf );
319- }
288+ conf .setFloat ("hbase.master.balancer.stochastic.minCostNeedBalance" , 1.0f );
289+ conf .setBoolean ("hbase.master.balancer.stochastic.runMaxSteps" , false );
290+ conf .setLong ("hbase.master.balancer.stochastic.maxSteps" , 5000L );
291+ conf .setBoolean (HConstants .HBASE_MASTER_LOADBALANCE_BYTABLE , true );
292+ loadBalancer .onConfigurationChange (conf );
293+ assertFalse (hasEmptyBalancerPlans (regionsPerServerPerTable ));
320294 }
321295
322296 private boolean hasEmptyBalancerPlans (int [] mockCluster ) {
@@ -439,7 +413,6 @@ public void testSkewCost() {
439413 @ Test
440414 public void testCostAfterUndoAction () {
441415 final int runs = 10 ;
442- loadBalancer .onConfigurationChange (conf );
443416 for (int [] mockCluster : clusterStateMocks ) {
444417 BalancerClusterState cluster = mockCluster (mockCluster );
445418 loadBalancer .initCosts (cluster );
@@ -542,17 +515,12 @@ public void testLosingRs() throws Exception {
542515
543516 @ Test
544517 public void testAdditionalCostFunction () {
545- try {
546- conf .set (StochasticLoadBalancer .COST_FUNCTIONS_COST_FUNCTIONS_KEY ,
547- DummyCostFunction .class .getName ());
518+ conf .set (StochasticLoadBalancer .COST_FUNCTIONS_COST_FUNCTIONS_KEY ,
519+ DummyCostFunction .class .getName ());
548520
549- loadBalancer .onConfigurationChange (conf );
550- assertTrue (Arrays .asList (loadBalancer .getCostFunctionNames ())
551- .contains (DummyCostFunction .class .getSimpleName ()));
552- } finally {
553- conf .unset (StochasticLoadBalancer .COST_FUNCTIONS_COST_FUNCTIONS_KEY );
554- loadBalancer .onConfigurationChange (conf );
555- }
521+ loadBalancer .onConfigurationChange (conf );
522+ assertTrue (Arrays .asList (loadBalancer .getCostFunctionNames ())
523+ .contains (DummyCostFunction .class .getSimpleName ()));
556524 }
557525
558526 @ Test
0 commit comments