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.rsgroup; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertFalse; 022import static org.junit.Assert.assertTrue; 023 024import java.util.List; 025import java.util.Map; 026import org.apache.hadoop.hbase.HBaseClassTestRule; 027import org.apache.hadoop.hbase.NamespaceDescriptor; 028import org.apache.hadoop.hbase.ServerName; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.Waiter; 031import org.apache.hadoop.hbase.Waiter.Predicate; 032import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 033import org.apache.hadoop.hbase.client.RegionInfo; 034import org.apache.hadoop.hbase.client.TableDescriptor; 035import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 036import org.apache.hadoop.hbase.testclassification.MediumTests; 037import org.apache.hadoop.hbase.util.Bytes; 038import org.junit.After; 039import org.junit.AfterClass; 040import org.junit.Before; 041import org.junit.BeforeClass; 042import org.junit.ClassRule; 043import org.junit.Test; 044import org.junit.experimental.categories.Category; 045import org.slf4j.Logger; 046import org.slf4j.LoggerFactory; 047 048import org.apache.hbase.thirdparty.com.google.common.collect.Sets; 049 050@Category({ MediumTests.class }) 051public class TestRSGroupsBalance extends TestRSGroupsBase { 052 053 @ClassRule 054 public static final HBaseClassTestRule CLASS_RULE = 055 HBaseClassTestRule.forClass(TestRSGroupsBalance.class); 056 057 protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsBalance.class); 058 059 @BeforeClass 060 public static void setUp() throws Exception { 061 setUpTestBeforeClass(); 062 } 063 064 @AfterClass 065 public static void tearDown() throws Exception { 066 tearDownAfterClass(); 067 } 068 069 @Before 070 public void beforeMethod() throws Exception { 071 setUpBeforeMethod(); 072 } 073 074 @After 075 public void afterMethod() throws Exception { 076 tearDownAfterMethod(); 077 } 078 079 @Test 080 public void testGroupBalance() throws Exception { 081 LOG.info(name.getMethodName()); 082 String newGroupName = getGroupName(name.getMethodName()); 083 addGroup(newGroupName, 3); 084 085 final TableName tableName = TableName.valueOf(tablePrefix + "_ns", name.getMethodName()); 086 admin.createNamespace(NamespaceDescriptor.create(tableName.getNamespaceAsString()) 087 .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, newGroupName).build()); 088 final TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName) 089 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("f")).build(); 090 byte[] startKey = Bytes.toBytes("aaaaa"); 091 byte[] endKey = Bytes.toBytes("zzzzz"); 092 admin.createTable(desc, startKey, endKey, 6); 093 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() { 094 @Override 095 public boolean evaluate() throws Exception { 096 List<String> regions = getTableRegionMap().get(tableName); 097 if (regions == null) { 098 return false; 099 } 100 return regions.size() >= 6; 101 } 102 }); 103 104 // make assignment uneven, move all regions to one server 105 Map<ServerName, List<String>> assignMap = getTableServerRegionMap().get(tableName); 106 final ServerName first = assignMap.entrySet().iterator().next().getKey(); 107 for (RegionInfo region : admin.getRegions(tableName)) { 108 if (!assignMap.get(first).contains(region.getRegionNameAsString())) { 109 admin.move(region.getEncodedNameAsBytes(), first); 110 } 111 } 112 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() { 113 @Override 114 public boolean evaluate() throws Exception { 115 Map<ServerName, List<String>> map = getTableServerRegionMap().get(tableName); 116 if (map == null) { 117 return true; 118 } 119 List<String> regions = map.get(first); 120 if (regions == null) { 121 return true; 122 } 123 return regions.size() >= 6; 124 } 125 }); 126 127 // balance the other group and make sure it doesn't affect the new group 128 admin.balancerSwitch(true, true); 129 rsGroupAdmin.balanceRSGroup(RSGroupInfo.DEFAULT_GROUP); 130 assertEquals(6, getTableServerRegionMap().get(tableName).get(first).size()); 131 132 // disable balance, balancer will not be run and return false 133 admin.balancerSwitch(false, true); 134 assertFalse(rsGroupAdmin.balanceRSGroup(newGroupName)); 135 assertEquals(6, getTableServerRegionMap().get(tableName).get(first).size()); 136 137 // enable balance 138 admin.balancerSwitch(true, true); 139 rsGroupAdmin.balanceRSGroup(newGroupName); 140 TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() { 141 @Override 142 public boolean evaluate() throws Exception { 143 for (List<String> regions : getTableServerRegionMap().get(tableName).values()) { 144 if (2 != regions.size()) { 145 return false; 146 } 147 } 148 return true; 149 } 150 }); 151 admin.balancerSwitch(false, true); 152 } 153 154 @Test 155 public void testMisplacedRegions() throws Exception { 156 final TableName tableName = TableName.valueOf(tablePrefix + "_testMisplacedRegions"); 157 LOG.info("testMisplacedRegions"); 158 159 final RSGroupInfo RSGroupInfo = addGroup("testMisplacedRegions", 1); 160 161 TEST_UTIL.createMultiRegionTable(tableName, new byte[] { 'f' }, 15); 162 TEST_UTIL.waitUntilAllRegionsAssigned(tableName); 163 164 rsGroupAdminEndpoint.getGroupInfoManager().moveTables(Sets.newHashSet(tableName), 165 RSGroupInfo.getName()); 166 167 admin.balancerSwitch(true, true); 168 assertTrue(rsGroupAdmin.balanceRSGroup(RSGroupInfo.getName())); 169 admin.balancerSwitch(false, true); 170 assertTrue(observer.preBalanceRSGroupCalled); 171 assertTrue(observer.postBalanceRSGroupCalled); 172 173 TEST_UTIL.waitFor(60000, new Predicate<Exception>() { 174 @Override 175 public boolean evaluate() throws Exception { 176 ServerName serverName = 177 ServerName.valueOf(RSGroupInfo.getServers().iterator().next().toString(), 1); 178 return admin.getConnection().getAdmin().getRegions(serverName).size() == 15; 179 } 180 }); 181 } 182 183}