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 java.util.List;
021import java.util.Optional;
022import java.util.concurrent.CountDownLatch;
023
024import org.apache.hadoop.hbase.HBaseClassTestRule;
025import org.apache.hadoop.hbase.HBaseTestingUtility;
026import org.apache.hadoop.hbase.TableName;
027import org.apache.hadoop.hbase.client.Admin;
028import org.apache.hadoop.hbase.client.Mutation;
029import org.apache.hadoop.hbase.client.RegionInfo;
030import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
031import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor;
032import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
033import org.apache.hadoop.hbase.coprocessor.MasterObserver;
034import org.apache.hadoop.hbase.coprocessor.ObserverContext;
035import org.apache.hadoop.hbase.testclassification.MasterTests;
036import org.apache.hadoop.hbase.testclassification.MediumTests;
037import org.apache.hadoop.hbase.util.Bytes;
038import org.junit.AfterClass;
039import org.junit.Assert;
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
047@Category({MasterTests.class, MediumTests.class})
048public class TestMasterAbortWhileMergingTable {
049
050  @ClassRule
051  public static final HBaseClassTestRule CLASS_RULE =
052      HBaseClassTestRule.forClass(TestMasterAbortWhileMergingTable.class);
053
054  private static final Logger LOG = LoggerFactory
055      .getLogger(TestMasterAbortWhileMergingTable.class);
056
057  protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
058  private static TableName TABLE_NAME = TableName.valueOf("test");
059  private static Admin admin;
060  private static byte[] CF = Bytes.toBytes("cf");
061  private static byte[] SPLITKEY = Bytes.toBytes("bbbbbbb");
062  private static CountDownLatch mergeCommitArrive = new CountDownLatch(1);
063
064
065
066  @BeforeClass
067  public static void setupCluster() throws Exception {
068    UTIL.getConfiguration().set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
069        MergeRegionObserver.class.getName());
070    UTIL.startMiniCluster(3);
071    admin = UTIL.getHBaseAdmin();
072    byte[][] splitKeys = new byte[1][];
073    splitKeys[0] = SPLITKEY;
074    UTIL.createTable(TABLE_NAME, CF, splitKeys);
075    UTIL.waitTableAvailable(TABLE_NAME);
076  }
077
078  @AfterClass
079  public static void cleanupTest() throws Exception {
080    try {
081      UTIL.shutdownMiniCluster();
082    } catch (Exception e) {
083      LOG.warn("failure shutting down cluster", e);
084    }
085  }
086
087  @Test
088  public void test() throws Exception {
089    List<RegionInfo> regionInfos = admin.getRegions(TABLE_NAME);
090    MergeTableRegionsProcedure mergeTableRegionsProcedure = new MergeTableRegionsProcedure(
091        UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor()
092            .getEnvironment(), new RegionInfo [] {regionInfos.get(0), regionInfos.get(1)}, false);
093    long procID = UTIL.getMiniHBaseCluster().getMaster().getMasterProcedureExecutor()
094        .submitProcedure(mergeTableRegionsProcedure);
095    mergeCommitArrive.await();
096    UTIL.getMiniHBaseCluster().stopMaster(0);
097    UTIL.getMiniHBaseCluster().startMaster();
098    //wait until master initialized
099    UTIL.waitFor(30000,
100      () -> UTIL.getMiniHBaseCluster().getMaster() != null && UTIL
101        .getMiniHBaseCluster().getMaster().isInitialized());
102    UTIL.waitFor(30000, () -> UTIL.getMiniHBaseCluster().getMaster()
103      .getMasterProcedureExecutor().isFinished(procID));
104    Assert.assertTrue("Found region RIT, that's impossible! " +
105      UTIL.getMiniHBaseCluster().getMaster().getAssignmentManager().getRegionsInTransition(),
106      UTIL.getMiniHBaseCluster().getMaster().getAssignmentManager()
107        .getRegionsInTransition().size() == 0);
108  }
109
110  public static class MergeRegionObserver implements MasterCoprocessor,
111      MasterObserver {
112
113    @Override
114    public Optional<MasterObserver> getMasterObserver() {
115      return Optional.of(this);
116    }
117
118    @Override
119    public void preMergeRegionsCommitAction(
120        ObserverContext<MasterCoprocessorEnvironment> ctx,
121        RegionInfo[] regionsToMerge, List<Mutation> metaEntries) {
122      mergeCommitArrive.countDown();
123      LOG.error("mergeCommitArrive countdown");
124    }
125  }
126
127}