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.procedure; 019 020import java.io.IOException; 021 022import org.apache.hadoop.fs.FileSystem; 023import org.apache.hadoop.fs.Path; 024import org.apache.hadoop.hbase.HBaseClassTestRule; 025import org.apache.hadoop.hbase.HBaseCommonTestingUtility; 026import org.apache.hadoop.hbase.HBaseTestingUtility; 027import org.apache.hadoop.hbase.TableName; 028import org.apache.hadoop.hbase.client.RegionInfo; 029import org.apache.hadoop.hbase.client.RegionInfoBuilder; 030import org.apache.hadoop.hbase.master.DummyRegionProcedure; 031import org.apache.hadoop.hbase.procedure2.Procedure; 032import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; 033import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer; 034import org.apache.hadoop.hbase.procedure2.ProcedureSuspendedException; 035import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility; 036import org.apache.hadoop.hbase.procedure2.ProcedureYieldException; 037import org.apache.hadoop.hbase.procedure2.store.wal.WALProcedureStore; 038import org.apache.hadoop.hbase.testclassification.MasterTests; 039import org.apache.hadoop.hbase.testclassification.SmallTests; 040import org.junit.BeforeClass; 041import org.junit.ClassRule; 042import org.junit.Test; 043import org.junit.experimental.categories.Category; 044import org.slf4j.Logger; 045import org.slf4j.LoggerFactory; 046 047import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 048import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 049 050 051@Category({MasterTests.class, SmallTests.class}) 052public class TestMasterProcedureSchedulerOnRestart { 053 @ClassRule public static final HBaseClassTestRule CLASS_RULE = HBaseClassTestRule 054 .forClass(TestMasterProcedureSchedulerOnRestart.class); 055 056 private static final Logger LOG = LoggerFactory 057 .getLogger(TestMasterProcedureSchedulerOnRestart.class); 058 private static final int PROCEDURE_EXECUTOR_SLOTS = 1; 059 private static final TableName tablename = TableName.valueOf("test:TestProcedureScheduler"); 060 private static RegionInfo regionInfo = RegionInfoBuilder.newBuilder(tablename).build(); 061 062 protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility(); 063 064 065 private static WALProcedureStore procStore; 066 067 private static ProcedureExecutor<MasterProcedureEnv> procExecutor; 068 069 private static HBaseCommonTestingUtility htu; 070 071 private static MasterProcedureEnv masterProcedureEnv; 072 073 074 private static FileSystem fs; 075 private static Path testDir; 076 private static Path logDir; 077 078 @BeforeClass 079 public static void setUp() throws Exception { 080 UTIL.startMiniCluster(1); 081 procExecutor = UTIL.getMiniHBaseCluster().getMaster() 082 .getMasterProcedureExecutor(); 083 } 084 085 @Test 086 public void testScheduler() throws Exception { 087 // Add a region procedure, but stuck there 088 long regionProc = procExecutor.submitProcedure(new DummyRegionProcedure( 089 UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor() 090 .getEnvironment(), regionInfo)); 091 WALProcedureStore walProcedureStore = (WALProcedureStore) procExecutor.getStore(); 092 // Roll the wal 093 walProcedureStore.rollWriterForTesting(); 094 Thread.sleep(500); 095 // Submit a table procedure 096 procExecutor.submitProcedure(new DummyTableProcedure( 097 UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor() 098 .getEnvironment(), tablename)); 099 // Restart the procExecutor 100 ProcedureTestingUtility.restart(procExecutor); 101 while (procExecutor.getProcedure(regionProc) == null) { 102 Thread.sleep(500); 103 } 104 DummyRegionProcedure dummyRegionProcedure = (DummyRegionProcedure) procExecutor 105 .getProcedure(regionProc); 106 // Resume the region procedure 107 dummyRegionProcedure.resume(); 108 // The region procedure should finish normally 109 UTIL.waitFor(5000, () -> dummyRegionProcedure.isFinished()); 110 111 } 112 113 public static class DummyTableProcedure extends 114 AbstractStateMachineTableProcedure<DummyRegionTableState> { 115 116 private TableName tableName; 117 118 public DummyTableProcedure() { 119 super(); 120 } 121 public DummyTableProcedure(final MasterProcedureEnv env, TableName tableName) { 122 super(null, null); 123 this.tableName = tableName; 124 } 125 126 @Override 127 public TableName getTableName() { 128 return tableName; 129 } 130 131 @Override 132 public TableOperationType getTableOperationType() { 133 return TableOperationType.CREATE; 134 } 135 136 @Override 137 protected Flow executeFromState(MasterProcedureEnv env, 138 DummyRegionTableState dummyRegionTableState) 139 throws ProcedureSuspendedException, ProcedureYieldException, 140 InterruptedException { 141 return null; 142 } 143 144 @Override 145 protected void rollbackState(MasterProcedureEnv env, 146 DummyRegionTableState dummyRegionTableState) 147 throws IOException, InterruptedException { 148 149 } 150 151 @Override 152 protected DummyRegionTableState getState(int stateId) { 153 return DummyRegionTableState.STATE; 154 } 155 156 @Override 157 protected int getStateId(DummyRegionTableState dummyRegionTableState) { 158 return 0; 159 } 160 161 @Override 162 protected DummyRegionTableState getInitialState() { 163 return DummyRegionTableState.STATE; 164 } 165 166 @Override 167 protected Procedure[] execute(final MasterProcedureEnv env) 168 throws ProcedureSuspendedException { 169 LOG.info("Finished execute"); 170 return null; 171 } 172 173 @Override 174 protected void serializeStateData(ProcedureStateSerializer serializer) 175 throws IOException { 176 super.serializeStateData(serializer); 177 serializer.serialize(ProtobufUtil.toProtoTableName(tableName)); 178 179 180 } 181 182 @Override 183 protected void deserializeStateData(ProcedureStateSerializer serializer) 184 throws IOException { 185 super.deserializeStateData(serializer); 186 tableName = ProtobufUtil 187 .toTableName(serializer.deserialize(HBaseProtos.TableName.class)); 188 189 } 190 191 @Override 192 protected LockState acquireLock(MasterProcedureEnv env) { 193 return super.acquireLock(env); 194 } 195 196 @Override 197 protected void releaseLock(MasterProcedureEnv env) { 198 super.releaseLock(env); 199 } 200 } 201 202 public enum DummyRegionTableState { 203 STATE 204 } 205 206 207}