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.junit.Assert.assertFalse; 021import static org.junit.Assert.assertTrue; 022 023import java.io.IOException; 024import org.apache.hadoop.hbase.HBaseClassTestRule; 025import org.apache.hadoop.hbase.HBaseTestingUtility; 026import org.apache.hadoop.hbase.TableName; 027import org.apache.hadoop.hbase.client.RegionInfo; 028import org.apache.hadoop.hbase.master.HMaster; 029import org.apache.hadoop.hbase.master.procedure.MasterProcedureConstants; 030import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; 031import org.apache.hadoop.hbase.master.procedure.MasterProcedureTestingUtility; 032import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; 033import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility; 034import org.apache.hadoop.hbase.regionserver.HRegion; 035import org.apache.hadoop.hbase.regionserver.HRegionServer; 036import org.apache.hadoop.hbase.testclassification.MasterTests; 037import org.apache.hadoop.hbase.testclassification.MediumTests; 038import org.apache.hadoop.hbase.util.Bytes; 039import org.junit.After; 040import org.junit.AfterClass; 041import org.junit.Before; 042import org.junit.BeforeClass; 043import org.junit.ClassRule; 044import org.junit.Rule; 045import org.junit.Test; 046import org.junit.experimental.categories.Category; 047import org.junit.rules.TestName; 048 049@Category({ MasterTests.class, MediumTests.class }) 050public class TestTransitRegionStateProcedure { 051 052 @ClassRule 053 public static final HBaseClassTestRule CLASS_RULE = 054 HBaseClassTestRule.forClass(TestTransitRegionStateProcedure.class); 055 056 private static HBaseTestingUtility UTIL = new HBaseTestingUtility(); 057 058 private static byte[] CF = Bytes.toBytes("cf"); 059 060 @Rule 061 public TestName name = new TestName(); 062 063 private TableName tableName; 064 065 @BeforeClass 066 public static void setUpBeforeClass() throws Exception { 067 UTIL.getConfiguration().setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1); 068 UTIL.startMiniCluster(3); 069 UTIL.getAdmin().balancerSwitch(false, true); 070 } 071 072 @AfterClass 073 public static void tearDownAfterClass() throws Exception { 074 UTIL.shutdownMiniCluster(); 075 } 076 077 @Before 078 public void setUp() throws IOException, InterruptedException { 079 tableName = TableName.valueOf(name.getMethodName()); 080 UTIL.createTable(tableName, CF); 081 UTIL.waitTableAvailable(tableName); 082 } 083 084 private void resetProcExecutorTestingKillFlag() { 085 ProcedureExecutor<MasterProcedureEnv> procExec = 086 UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor(); 087 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false); 088 assertTrue("expected executor to be running", procExec.isRunning()); 089 } 090 091 @After 092 public void tearDown() throws IOException { 093 resetProcExecutorTestingKillFlag(); 094 UTIL.deleteTable(tableName); 095 } 096 097 private void testRecoveryAndDoubleExcution(TransitRegionStateProcedure proc) throws Exception { 098 HMaster master = UTIL.getHBaseCluster().getMaster(); 099 AssignmentManager am = master.getAssignmentManager(); 100 RegionStateNode regionNode = am.getRegionStates().getRegionStateNode(proc.getRegion()); 101 assertFalse(regionNode.isInTransition()); 102 regionNode.setProcedure(proc); 103 assertTrue(regionNode.isInTransition()); 104 ProcedureExecutor<MasterProcedureEnv> procExec = master.getMasterProcedureExecutor(); 105 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); 106 long procId = procExec.submitProcedure(proc); 107 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId); 108 regionNode = am.getRegionStates().getRegionStateNode(proc.getRegion()); 109 assertFalse(regionNode.isInTransition()); 110 } 111 112 @Test 113 public void testRecoveryAndDoubleExecutionMove() throws Exception { 114 MasterProcedureEnv env = 115 UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor().getEnvironment(); 116 HRegion region = UTIL.getMiniHBaseCluster().getRegions(tableName).get(0); 117 long openSeqNum = region.getOpenSeqNum(); 118 TransitRegionStateProcedure proc = 119 TransitRegionStateProcedure.move(env, region.getRegionInfo(), null); 120 testRecoveryAndDoubleExcution(proc); 121 HRegion region2 = UTIL.getMiniHBaseCluster().getRegions(tableName).get(0); 122 long openSeqNum2 = region2.getOpenSeqNum(); 123 // confirm that the region is successfully opened 124 assertTrue(openSeqNum2 > openSeqNum); 125 } 126 127 @Test 128 public void testRecoveryAndDoubleExecutionReopen() throws Exception { 129 MasterProcedureEnv env = 130 UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor().getEnvironment(); 131 HRegionServer rs = UTIL.getRSForFirstRegionInTable(tableName); 132 HRegion region = rs.getRegions(tableName).get(0); 133 long openSeqNum = region.getOpenSeqNum(); 134 TransitRegionStateProcedure proc = 135 TransitRegionStateProcedure.reopen(env, region.getRegionInfo()); 136 testRecoveryAndDoubleExcution(proc); 137 // should still be on the same RS 138 HRegion region2 = rs.getRegions(tableName).get(0); 139 long openSeqNum2 = region2.getOpenSeqNum(); 140 // confirm that the region is successfully opened 141 assertTrue(openSeqNum2 > openSeqNum); 142 } 143 144 @Test 145 public void testRecoveryAndDoubleExecutionUnassignAndAssign() throws Exception { 146 HMaster master = UTIL.getMiniHBaseCluster().getMaster(); 147 MasterProcedureEnv env = master.getMasterProcedureExecutor().getEnvironment(); 148 HRegion region = UTIL.getMiniHBaseCluster().getRegions(tableName).get(0); 149 RegionInfo regionInfo = region.getRegionInfo(); 150 long openSeqNum = region.getOpenSeqNum(); 151 TransitRegionStateProcedure unassign = TransitRegionStateProcedure.unassign(env, regionInfo); 152 testRecoveryAndDoubleExcution(unassign); 153 AssignmentManager am = master.getAssignmentManager(); 154 assertTrue(am.getRegionStates().getRegionState(regionInfo).isClosed()); 155 156 TransitRegionStateProcedure assign = TransitRegionStateProcedure.assign(env, regionInfo, null); 157 testRecoveryAndDoubleExcution(assign); 158 159 HRegion region2 = UTIL.getMiniHBaseCluster().getRegions(tableName).get(0); 160 long openSeqNum2 = region2.getOpenSeqNum(); 161 // confirm that the region is successfully opened 162 assertTrue(openSeqNum2 > openSeqNum); 163 } 164}