001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.master.assignment; 020 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.fail; 023 024import java.io.IOException; 025import java.util.ArrayList; 026import java.util.List; 027 028import org.apache.hadoop.conf.Configuration; 029import org.apache.hadoop.hbase.HBaseClassTestRule; 030import org.apache.hadoop.hbase.HBaseTestingUtility; 031import org.apache.hadoop.hbase.HConstants; 032import org.apache.hadoop.hbase.ServerName; 033import org.apache.hadoop.hbase.TableName; 034import org.apache.hadoop.hbase.client.RegionInfo; 035import org.apache.hadoop.hbase.client.RegionReplicaUtil; 036import org.apache.hadoop.hbase.client.Table; 037import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 038import org.apache.hadoop.hbase.regionserver.HRegionServer; 039import org.apache.hadoop.hbase.regionserver.Region; 040import org.apache.hadoop.hbase.testclassification.LargeTests; 041import org.apache.hadoop.hbase.testclassification.MasterTests; 042import org.apache.hadoop.hbase.util.Bytes; 043import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread; 044import org.apache.hadoop.hbase.util.RegionSplitter; 045import org.junit.AfterClass; 046import org.junit.BeforeClass; 047import org.junit.ClassRule; 048import org.junit.Rule; 049import org.junit.Test; 050import org.junit.experimental.categories.Category; 051import org.junit.rules.TestName; 052import org.slf4j.Logger; 053import org.slf4j.LoggerFactory; 054 055@Category({ MasterTests.class, LargeTests.class }) 056public class TestRegionReplicaSplit { 057 @ClassRule 058 public static final HBaseClassTestRule CLASS_RULE = 059 HBaseClassTestRule.forClass(TestRegionReplicaSplit.class); 060 private static final Logger LOG = LoggerFactory.getLogger(TestRegionReplicaSplit.class); 061 062 private static final int NB_SERVERS = 4; 063 private static Table table; 064 065 private static final HBaseTestingUtility HTU = new HBaseTestingUtility(); 066 private static final byte[] f = HConstants.CATALOG_FAMILY; 067 068 @BeforeClass 069 public static void beforeClass() throws Exception { 070 HTU.getConfiguration().setInt("hbase.master.wait.on.regionservers.mintostart", 3); 071 HTU.startMiniCluster(NB_SERVERS); 072 final TableName tableName = TableName.valueOf(TestRegionReplicaSplit.class.getSimpleName()); 073 074 // Create table then get the single region for our new table. 075 createTable(tableName); 076 } 077 078 @Rule 079 public TestName name = new TestName(); 080 081 private static void createTable(final TableName tableName) throws IOException { 082 TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName); 083 builder.setRegionReplication(3); 084 // create a table with 3 replication 085 table = HTU.createTable(builder.build(), new byte[][] { f }, getSplits(2), 086 new Configuration(HTU.getConfiguration())); 087 } 088 089 private static byte[][] getSplits(int numRegions) { 090 RegionSplitter.UniformSplit split = new RegionSplitter.UniformSplit(); 091 split.setFirstRow(Bytes.toBytes(0L)); 092 split.setLastRow(Bytes.toBytes(Long.MAX_VALUE)); 093 return split.split(numRegions); 094 } 095 096 @AfterClass 097 public static void afterClass() throws Exception { 098 HRegionServer.TEST_SKIP_REPORTING_TRANSITION = false; 099 table.close(); 100 HTU.shutdownMiniCluster(); 101 } 102 103 @Test 104 public void testRegionReplicaSplitRegionAssignment() throws Exception { 105 HTU.loadNumericRows(table, f, 0, 3); 106 // split the table 107 List<RegionInfo> regions = new ArrayList<RegionInfo>(); 108 for (RegionServerThread rs : HTU.getMiniHBaseCluster().getRegionServerThreads()) { 109 for (Region r : rs.getRegionServer().getRegions(table.getName())) { 110 System.out.println("the region before split is is " + r.getRegionInfo() 111 + rs.getRegionServer().getServerName()); 112 regions.add(r.getRegionInfo()); 113 } 114 } 115 HTU.getAdmin().split(table.getName(), Bytes.toBytes(1)); 116 int count = 0; 117 while (true) { 118 for (RegionServerThread rs : HTU.getMiniHBaseCluster().getRegionServerThreads()) { 119 for (Region r : rs.getRegionServer().getRegions(table.getName())) { 120 count++; 121 } 122 } 123 if (count >= 9) { 124 break; 125 } 126 count = 0; 127 } 128 List<ServerName> newRegionLocations = new ArrayList<ServerName>(); 129 for (RegionServerThread rs : HTU.getMiniHBaseCluster().getRegionServerThreads()) { 130 RegionInfo prevInfo = null; 131 for (Region r : rs.getRegionServer().getRegions(table.getName())) { 132 if (!regions.contains(r.getRegionInfo()) 133 && !RegionReplicaUtil.isDefaultReplica(r.getRegionInfo())) { 134 LOG.info("The region is " + r.getRegionInfo() + " the location is " 135 + rs.getRegionServer().getServerName()); 136 if (!RegionReplicaUtil.isDefaultReplica(r.getRegionInfo()) 137 && newRegionLocations.contains(rs.getRegionServer().getServerName()) 138 && prevInfo != null 139 && Bytes.equals(prevInfo.getStartKey(), r.getRegionInfo().getStartKey()) 140 && Bytes.equals(prevInfo.getEndKey(), r.getRegionInfo().getEndKey())) { 141 fail("Splitted regions should not be assigned to same region server"); 142 } else { 143 prevInfo = r.getRegionInfo(); 144 if (!RegionReplicaUtil.isDefaultReplica(r.getRegionInfo()) 145 && !newRegionLocations.contains(rs.getRegionServer().getServerName())) { 146 newRegionLocations.add(rs.getRegionServer().getServerName()); 147 } 148 } 149 } 150 } 151 } 152 // since we assign the daughter regions in round robin fashion, both the daugther region 153 // replicas will be assigned to two unique servers. 154 assertEquals("The new regions should be assigned to 3 unique servers ", 3, 155 newRegionLocations.size()); 156 } 157}