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.assignment; 019 020import static org.apache.hadoop.hbase.master.assignment.AssignmentTestingUtil.insertData; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertNotNull; 023import static org.junit.Assert.assertTrue; 024 025import java.util.List; 026import java.util.Map; 027import org.apache.hadoop.conf.Configuration; 028import org.apache.hadoop.hbase.HBaseClassTestRule; 029import org.apache.hadoop.hbase.HBaseTestingUtility; 030import org.apache.hadoop.hbase.ServerName; 031import org.apache.hadoop.hbase.StartMiniClusterOption; 032import org.apache.hadoop.hbase.TableName; 033import org.apache.hadoop.hbase.client.RegionInfo; 034import org.apache.hadoop.hbase.client.TableDescriptor; 035import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; 036import org.apache.hadoop.hbase.master.procedure.MasterProcedureTestingUtility; 037import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; 038import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility; 039import org.apache.hadoop.hbase.regionserver.HRegion; 040import org.apache.hadoop.hbase.testclassification.MasterTests; 041import org.apache.hadoop.hbase.testclassification.MediumTests; 042import org.apache.hadoop.hbase.util.Bytes; 043import org.apache.hadoop.hbase.util.JVMClusterUtil; 044import org.junit.After; 045import org.junit.AfterClass; 046import org.junit.Before; 047import org.junit.BeforeClass; 048import org.junit.ClassRule; 049import org.junit.Rule; 050import org.junit.Test; 051import org.junit.experimental.categories.Category; 052import org.junit.rules.TestName; 053import org.slf4j.Logger; 054import org.slf4j.LoggerFactory; 055 056@Category({ MasterTests.class, MediumTests.class }) 057public class TestRegionSplit { 058 059 @ClassRule 060 public static final HBaseClassTestRule CLASS_RULE = 061 HBaseClassTestRule.forClass(TestRegionSplit.class); 062 063 private static final Logger LOG = LoggerFactory.getLogger(TestRegionSplit.class); 064 065 protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility(); 066 067 private static String columnFamilyName = "cf"; 068 069 private static final int startRowNum = 11; 070 private static final int rowCount = 60; 071 072 @Rule 073 public TestName name = new TestName(); 074 075 private static void setupConf(Configuration conf) { 076 } 077 078 @BeforeClass 079 public static void setupCluster() throws Exception { 080 setupConf(UTIL.getConfiguration()); 081 StartMiniClusterOption option = 082 StartMiniClusterOption.builder().numMasters(1).numRegionServers(3).numDataNodes(3).build(); 083 UTIL.startMiniCluster(option); 084 } 085 086 @AfterClass 087 public static void cleanupTest() throws Exception { 088 try { 089 UTIL.shutdownMiniCluster(); 090 } catch (Exception e) { 091 LOG.warn("failure shutting down cluster", e); 092 } 093 } 094 095 @Before 096 public void setup() throws Exception { 097 // Turn off the meta scanner so it don't remove parent on us. 098 UTIL.getHBaseCluster().getMaster().setCatalogJanitorEnabled(false); 099 // Disable compaction. 100 for (int i = 0; i < UTIL.getHBaseCluster().getLiveRegionServerThreads().size(); i++) { 101 UTIL.getHBaseCluster().getRegionServer(i).getCompactSplitThread().switchCompaction(false); 102 } 103 } 104 105 @After 106 public void tearDown() throws Exception { 107 for (TableDescriptor htd : UTIL.getAdmin().listTableDescriptors()) { 108 UTIL.deleteTable(htd.getTableName()); 109 } 110 } 111 112 @Test 113 public void testSplitTableRegion() throws Exception { 114 final TableName tableName = TableName.valueOf(name.getMethodName()); 115 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 116 117 RegionInfo[] regions = 118 MasterProcedureTestingUtility.createTable(procExec, tableName, null, columnFamilyName); 119 insertData(UTIL, tableName, rowCount, startRowNum, columnFamilyName); 120 int splitRowNum = startRowNum + rowCount / 2; 121 byte[] splitKey = Bytes.toBytes("" + splitRowNum); 122 123 assertTrue("not able to find a splittable region", regions != null); 124 assertTrue("not able to find a splittable region", regions.length == 1); 125 126 // Split region of the table 127 long procId = procExec.submitProcedure( 128 new SplitTableRegionProcedure(procExec.getEnvironment(), regions[0], splitKey)); 129 // Wait the completion 130 ProcedureTestingUtility.waitProcedure(procExec, procId); 131 ProcedureTestingUtility.assertProcNotFailed(procExec, procId); 132 133 assertTrue("not able to split table", UTIL.getHBaseCluster().getRegions(tableName).size() == 2); 134 135 // disable table 136 UTIL.getAdmin().disableTable(tableName); 137 Thread.sleep(500); 138 139 // stop master 140 UTIL.getHBaseCluster().stopMaster(0); 141 UTIL.getHBaseCluster().waitOnMaster(0); 142 Thread.sleep(500); 143 144 // restart master 145 JVMClusterUtil.MasterThread t = UTIL.getHBaseCluster().startMaster(); 146 Thread.sleep(500); 147 148 UTIL.invalidateConnection(); 149 // enable table 150 UTIL.getAdmin().enableTable(tableName); 151 Thread.sleep(500); 152 153 List<HRegion> tableRegions = UTIL.getHBaseCluster().getRegions(tableName); 154 assertEquals("Table region not correct.", 2, tableRegions.size()); 155 Map<RegionInfo, ServerName> regionInfoMap = UTIL.getHBaseCluster().getMaster() 156 .getAssignmentManager().getRegionStates().getRegionAssignments(); 157 assertEquals(regionInfoMap.get(tableRegions.get(0).getRegionInfo()), 158 regionInfoMap.get(tableRegions.get(1).getRegionInfo())); 159 } 160 161 @Test 162 public void testSplitStoreFiles() throws Exception { 163 final TableName tableName = TableName.valueOf(name.getMethodName()); 164 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 165 166 RegionInfo[] regions = 167 MasterProcedureTestingUtility.createTable(procExec, tableName, null, columnFamilyName); 168 // flush the memstore 169 insertData(UTIL, tableName, rowCount, startRowNum, true, columnFamilyName); 170 171 // assert the hfile count of the table 172 int storeFilesCountSum = 0; 173 for (HRegion region : UTIL.getHBaseCluster().getRegions(tableName)) { 174 storeFilesCountSum += region.getStore(Bytes.toBytes(columnFamilyName)).getStorefiles().size(); 175 } 176 assertEquals(1, storeFilesCountSum); 177 178 // split at the start row 179 byte[] splitKey = Bytes.toBytes("" + startRowNum); 180 181 assertNotNull("Not able to find a splittable region", regions); 182 assertEquals("Not able to find a splittable region", 1, regions.length); 183 184 // Split region of the table 185 long procId = procExec.submitProcedure( 186 new SplitTableRegionProcedure(procExec.getEnvironment(), regions[0], splitKey)); 187 // Wait the completion 188 ProcedureTestingUtility.waitProcedure(procExec, procId); 189 ProcedureTestingUtility.assertProcNotFailed(procExec, procId); 190 191 assertEquals("Not able to split table", 2, UTIL.getHBaseCluster().getRegions(tableName).size()); 192 193 // assert sum of the hfiles of all regions 194 int childStoreFilesSum = 0; 195 for (HRegion region : UTIL.getHBaseCluster().getRegions(tableName)) { 196 childStoreFilesSum += region.getStore(Bytes.toBytes(columnFamilyName)).getStorefiles().size(); 197 } 198 assertEquals(1, childStoreFilesSum); 199 200 List<HRegion> tableRegions = UTIL.getHBaseCluster().getRegions(tableName); 201 assertEquals("Table region not correct.", 2, tableRegions.size()); 202 Map<RegionInfo, ServerName> regionInfoMap = UTIL.getHBaseCluster().getMaster() 203 .getAssignmentManager().getRegionStates().getRegionAssignments(); 204 assertEquals(regionInfoMap.get(tableRegions.get(0).getRegionInfo()), 205 regionInfoMap.get(tableRegions.get(1).getRegionInfo())); 206 } 207 208 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() { 209 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor(); 210 } 211}