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.apache.hadoop.hbase.master.balancer.BalancerConditionalsTestUtil.validateAssertionsWithRetries;
021
022import java.util.List;
023import org.apache.hadoop.hbase.HBaseTestingUtil;
024import org.apache.hadoop.hbase.HConstants;
025import org.apache.hadoop.hbase.TableName;
026import org.apache.hadoop.hbase.client.Admin;
027import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
028import org.apache.hadoop.hbase.client.Connection;
029import org.apache.hadoop.hbase.client.RegionInfo;
030import org.apache.hadoop.hbase.client.TableDescriptor;
031import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
032import org.apache.hadoop.hbase.testclassification.LargeTests;
033import org.apache.hadoop.hbase.testclassification.MasterTests;
034import org.apache.hadoop.hbase.util.Bytes;
035import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil;
036import org.junit.jupiter.api.AfterEach;
037import org.junit.jupiter.api.BeforeEach;
038import org.junit.jupiter.api.Tag;
039import org.junit.jupiter.api.Test;
040import org.slf4j.Logger;
041import org.slf4j.LoggerFactory;
042
043@Tag(LargeTests.TAG)
044@Tag(MasterTests.TAG)
045public class TestReplicaDistributionBalancerConditional {
046
047  private static final Logger LOG =
048    LoggerFactory.getLogger(TestReplicaDistributionBalancerConditional.class);
049  private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();
050  private static final int REPLICAS = 3;
051  private static final int NUM_SERVERS = REPLICAS;
052  private static final int REGIONS_PER_SERVER = 5;
053
054  @BeforeEach
055  public void setUp() throws Exception {
056    DistributeReplicasTestConditional
057      .enableConditionalReplicaDistributionForTest(TEST_UTIL.getConfiguration());
058    TEST_UTIL.getConfiguration()
059      .setBoolean(ServerRegionReplicaUtil.REGION_REPLICA_REPLICATION_CONF_KEY, true);
060    TEST_UTIL.getConfiguration().setLong(HConstants.HBASE_BALANCER_PERIOD, 1000L);
061    TEST_UTIL.getConfiguration().setBoolean("hbase.master.balancer.stochastic.runMaxSteps", true);
062
063    // turn off replica cost functions
064    TEST_UTIL.getConfiguration()
065      .setLong("hbase.master.balancer.stochastic.regionReplicaRackCostKey", 0);
066    TEST_UTIL.getConfiguration()
067      .setLong("hbase.master.balancer.stochastic.regionReplicaHostCostKey", 0);
068
069    TEST_UTIL.startMiniCluster(NUM_SERVERS);
070  }
071
072  @AfterEach
073  public void tearDown() throws Exception {
074    TEST_UTIL.shutdownMiniCluster();
075  }
076
077  @Test
078  public void testReplicaDistribution() throws Exception {
079    Connection connection = TEST_UTIL.getConnection();
080    Admin admin = connection.getAdmin();
081
082    // Create a "replicated_table" with region replicas
083    TableName replicatedTableName = TableName.valueOf("replicated_table");
084    TableDescriptor replicatedTableDescriptor =
085      TableDescriptorBuilder.newBuilder(replicatedTableName)
086        .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("0")).build())
087        .setRegionReplication(REPLICAS).build();
088    admin.createTable(replicatedTableDescriptor,
089      BalancerConditionalsTestUtil.generateSplits(REGIONS_PER_SERVER * NUM_SERVERS));
090
091    // Pause the balancer
092    admin.balancerSwitch(false, true);
093
094    // Collect all region replicas and place them on one RegionServer
095    List<RegionInfo> allRegions = admin.getRegions(replicatedTableName);
096    String targetServer =
097      TEST_UTIL.getHBaseCluster().getRegionServer(0).getServerName().getServerName();
098
099    for (RegionInfo region : allRegions) {
100      admin.move(region.getEncodedNameAsBytes(), Bytes.toBytes(targetServer));
101    }
102
103    BalancerConditionalsTestUtil.printRegionLocations(TEST_UTIL.getConnection());
104    validateAssertionsWithRetries(TEST_UTIL, false, () -> BalancerConditionalsTestUtil
105      .validateReplicaDistribution(connection, replicatedTableName, false));
106
107    // Unpause the balancer and trigger balancing
108    admin.balancerSwitch(true, true);
109    admin.balance();
110
111    validateAssertionsWithRetries(TEST_UTIL, true, () -> BalancerConditionalsTestUtil
112      .validateReplicaDistribution(connection, replicatedTableName, true));
113    BalancerConditionalsTestUtil.printRegionLocations(TEST_UTIL.getConnection());
114  }
115}