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 org.apache.hadoop.fs.Path;
021import org.apache.hadoop.hbase.HBaseTestingUtil;
022import org.apache.hadoop.hbase.StartTestingClusterOption;
023import org.apache.hadoop.hbase.procedure2.Procedure;
024import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
025import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
026import org.junit.AfterClass;
027import org.junit.BeforeClass;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030
031public abstract class MasterFailoverWithProceduresTestBase {
032
033  private static final Logger LOG =
034    LoggerFactory.getLogger(MasterFailoverWithProceduresTestBase.class);
035
036  protected static final HBaseTestingUtil UTIL = new HBaseTestingUtil();
037
038  @BeforeClass
039  public static void setUp() throws Exception {
040    UTIL.getConfiguration().setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1);
041    StartTestingClusterOption option = StartTestingClusterOption.builder().numMasters(2).build();
042    UTIL.startMiniCluster(option);
043
044    final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
045    ProcedureTestingUtility.setToggleKillBeforeStoreUpdate(procExec, false);
046    ProcedureTestingUtility.setKillBeforeStoreUpdate(procExec, false);
047  }
048
049  @AfterClass
050  public static void tearDown() throws Exception {
051    UTIL.shutdownMiniCluster();
052  }
053
054  // ==========================================================================
055  // Helpers
056  // ==========================================================================
057  protected static ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
058    return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
059  }
060
061  protected static Path getRootDir() {
062    return UTIL.getHBaseCluster().getMaster().getMasterFileSystem().getRootDir();
063  }
064
065  protected static void testRecoveryAndDoubleExecution(final HBaseTestingUtil testUtil,
066    final long procId, final int lastStepBeforeFailover) throws Exception {
067    ProcedureExecutor<MasterProcedureEnv> procExec =
068      testUtil.getHBaseCluster().getMaster().getMasterProcedureExecutor();
069    ProcedureTestingUtility.waitProcedure(procExec, procId);
070
071    final Procedure<?> proc = procExec.getProcedure(procId);
072    for (int i = 0; i < lastStepBeforeFailover; ++i) {
073      LOG.info("Restart " + i + " exec state: " + proc);
074      ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
075      MasterProcedureTestingUtility.restartMasterProcedureExecutor(procExec);
076      ProcedureTestingUtility.waitProcedure(procExec, procId);
077    }
078    ProcedureTestingUtility.assertProcNotYetCompleted(procExec, procId);
079
080    LOG.info("Trigger master failover");
081    MasterProcedureTestingUtility.masterFailover(testUtil);
082
083    procExec = testUtil.getHBaseCluster().getMaster().getMasterProcedureExecutor();
084    ProcedureTestingUtility.waitProcedure(procExec, procId);
085    ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
086  }
087}