001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.master.balancer; 019 020import static org.mockito.Mockito.mock; 021import static org.mockito.Mockito.when; 022 023import java.util.Arrays; 024import java.util.List; 025import java.util.Map; 026import org.apache.hadoop.hbase.HBaseClassTestRule; 027import org.apache.hadoop.hbase.HConstants; 028import org.apache.hadoop.hbase.ServerName; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.client.LogEntry; 031import org.apache.hadoop.hbase.client.RegionInfo; 032import org.apache.hadoop.hbase.master.MasterServices; 033import org.apache.hadoop.hbase.master.RegionPlan; 034import org.apache.hadoop.hbase.namequeues.BalancerDecisionDetails; 035import org.apache.hadoop.hbase.namequeues.request.NamedQueueGetRequest; 036import org.apache.hadoop.hbase.namequeues.response.NamedQueueGetResponse; 037import org.apache.hadoop.hbase.testclassification.MasterTests; 038import org.apache.hadoop.hbase.testclassification.MediumTests; 039import org.junit.Assert; 040import org.junit.ClassRule; 041import org.junit.Test; 042import org.junit.experimental.categories.Category; 043 044import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 045import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos; 046import org.apache.hadoop.hbase.shaded.protobuf.generated.RecentLogs; 047 048/** 049 * Test BalancerDecision ring buffer using namedQueue interface 050 */ 051@Category({ MasterTests.class, MediumTests.class }) 052public class TestBalancerDecision extends StochasticBalancerTestBase { 053 054 @ClassRule 055 public static final HBaseClassTestRule CLASS_RULE = 056 HBaseClassTestRule.forClass(TestBalancerDecision.class); 057 058 @Test 059 public void testBalancerDecisions() { 060 conf.setBoolean("hbase.master.balancer.decision.buffer.enabled", true); 061 MasterServices services = mock(MasterServices.class); 062 when(services.getConfiguration()).thenReturn(conf); 063 MasterClusterInfoProvider provider = new MasterClusterInfoProvider(services); 064 loadBalancer.setClusterInfoProvider(provider); 065 loadBalancer.onConfigurationChange(conf); 066 float minCost = conf.getFloat("hbase.master.balancer.stochastic.minCostNeedBalance", 0.05f); 067 float slop = conf.getFloat(HConstants.LOAD_BALANCER_SLOP_KEY, 0.2f); 068 conf.setFloat("hbase.master.balancer.stochastic.minCostNeedBalance", 1.0f); 069 conf.setFloat(HConstants.LOAD_BALANCER_SLOP_KEY, -1f); 070 try { 071 // Test with/without per table balancer. 072 boolean[] perTableBalancerConfigs = { true, false }; 073 for (boolean isByTable : perTableBalancerConfigs) { 074 conf.setBoolean(HConstants.HBASE_MASTER_LOADBALANCE_BYTABLE, isByTable); 075 loadBalancer.onConfigurationChange(conf); 076 for (int[] mockCluster : clusterStateMocks) { 077 Map<ServerName, List<RegionInfo>> servers = mockClusterServers(mockCluster); 078 Map<TableName, Map<ServerName, List<RegionInfo>>> LoadOfAllTable = 079 (Map) mockClusterServersWithTables(servers); 080 List<RegionPlan> plans = loadBalancer.balanceCluster(LoadOfAllTable); 081 boolean emptyPlans = plans == null || plans.isEmpty(); 082 Assert.assertTrue(emptyPlans || needsBalanceIdleRegion(mockCluster)); 083 } 084 } 085 final NamedQueueGetRequest namedQueueGetRequest = new NamedQueueGetRequest(); 086 namedQueueGetRequest.setNamedQueueEvent(BalancerDecisionDetails.BALANCER_DECISION_EVENT); 087 namedQueueGetRequest 088 .setBalancerDecisionsRequest(MasterProtos.BalancerDecisionsRequest.getDefaultInstance()); 089 NamedQueueGetResponse namedQueueGetResponse = 090 provider.getNamedQueueRecorder().getNamedQueueRecords(namedQueueGetRequest); 091 List<RecentLogs.BalancerDecision> balancerDecisions = 092 namedQueueGetResponse.getBalancerDecisions(); 093 MasterProtos.BalancerDecisionsResponse response = MasterProtos.BalancerDecisionsResponse 094 .newBuilder().addAllBalancerDecision(balancerDecisions).build(); 095 List<LogEntry> balancerDecisionRecords = ProtobufUtil.getBalancerDecisionEntries(response); 096 Assert.assertTrue(balancerDecisionRecords.size() > 160); 097 } finally { 098 // reset config 099 conf.unset(HConstants.HBASE_MASTER_LOADBALANCE_BYTABLE); 100 conf.setFloat("hbase.master.balancer.stochastic.minCostNeedBalance", minCost); 101 conf.setFloat(HConstants.LOAD_BALANCER_SLOP_KEY, slop); 102 loadBalancer.onConfigurationChange(conf); 103 } 104 } 105 106 private static boolean needsBalanceIdleRegion(int[] cluster) { 107 return (Arrays.stream(cluster).anyMatch(x -> x > 1)) 108 && (Arrays.stream(cluster).anyMatch(x -> x < 1)); 109 } 110}