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}