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;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertTrue;
022
023import java.util.List;
024import java.util.NavigableSet;
025import org.apache.hadoop.conf.Configuration;
026import org.apache.hadoop.hbase.HBaseClassTestRule;
027import org.apache.hadoop.hbase.HBaseConfiguration;
028import org.apache.hadoop.hbase.HBaseTestingUtility;
029import org.apache.hadoop.hbase.MiniHBaseCluster;
030import org.apache.hadoop.hbase.StartMiniClusterOption;
031import org.apache.hadoop.hbase.TableName;
032import org.apache.hadoop.hbase.client.Admin;
033import org.apache.hadoop.hbase.client.RegionLocator;
034import org.apache.hadoop.hbase.client.Table;
035import org.apache.hadoop.hbase.client.TableState;
036import org.apache.hadoop.hbase.testclassification.LargeTests;
037import org.apache.hadoop.hbase.testclassification.MasterTests;
038import org.apache.hadoop.hbase.util.Bytes;
039import org.apache.hadoop.hbase.util.JVMClusterUtil.MasterThread;
040import org.junit.ClassRule;
041import org.junit.Rule;
042import org.junit.Test;
043import org.junit.experimental.categories.Category;
044import org.junit.rules.TestName;
045import org.slf4j.Logger;
046import org.slf4j.LoggerFactory;
047
048@Category({MasterTests.class, LargeTests.class})
049public class TestMasterRestartAfterDisablingTable {
050
051  @ClassRule
052  public static final HBaseClassTestRule CLASS_RULE =
053      HBaseClassTestRule.forClass(TestMasterRestartAfterDisablingTable.class);
054
055  private static final Logger LOG =
056      LoggerFactory.getLogger(TestMasterRestartAfterDisablingTable.class);
057
058  @Rule
059  public TestName name = new TestName();
060
061  @Test
062  public void testForCheckingIfEnableAndDisableWorksFineAfterSwitch()
063      throws Exception {
064    final int NUM_MASTERS = 2;
065    final int NUM_REGIONS_TO_CREATE = 4;
066
067    // Start the cluster
068    log("Starting cluster");
069    Configuration conf = HBaseConfiguration.create();
070    HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(conf);
071    StartMiniClusterOption option = StartMiniClusterOption.builder()
072        .numMasters(NUM_MASTERS).build();
073    TEST_UTIL.startMiniCluster(option);
074    MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
075    log("Waiting for active/ready master");
076    cluster.waitForActiveAndReadyMaster();
077
078    // Create a table with regions
079    final TableName tableName = TableName.valueOf(name.getMethodName());
080    byte[] family = Bytes.toBytes("family");
081    log("Creating table with " + NUM_REGIONS_TO_CREATE + " regions");
082    Table ht = TEST_UTIL.createMultiRegionTable(tableName, family, NUM_REGIONS_TO_CREATE);
083    int numRegions = -1;
084    try (RegionLocator r = TEST_UTIL.getConnection().getRegionLocator(tableName)) {
085      numRegions = r.getStartKeys().length;
086    }
087    numRegions += 1; // catalogs
088    log("Waiting for no more RIT\n");
089    TEST_UTIL.waitUntilNoRegionsInTransition(60000);
090    log("Disabling table\n");
091    TEST_UTIL.getAdmin().disableTable(tableName);
092
093    NavigableSet<String> regions = HBaseTestingUtility.getAllOnlineRegions(cluster);
094    assertEquals(
095        "The number of regions for the table tableRestart should be 0 and only"
096            + "the catalog and namespace tables should be present.", 2, regions.size());
097
098    List<MasterThread> masterThreads = cluster.getMasterThreads();
099    MasterThread activeMaster = null;
100    if (masterThreads.get(0).getMaster().isActiveMaster()) {
101      activeMaster = masterThreads.get(0);
102    } else {
103      activeMaster = masterThreads.get(1);
104    }
105    activeMaster.getMaster().stop(
106        "stopping the active master so that the backup can become active");
107    cluster.hbaseCluster.waitOnMaster(activeMaster);
108    cluster.waitForActiveAndReadyMaster();
109
110    assertTrue("The table should not be in enabled state",
111        cluster.getMaster().getTableStateManager().isTableState(
112        TableName.valueOf(name.getMethodName()), TableState.State.DISABLED,
113        TableState.State.DISABLING));
114    log("Enabling table\n");
115    // Need a new Admin, the previous one is on the old master
116    Admin admin = TEST_UTIL.getAdmin();
117    admin.enableTable(tableName);
118    admin.close();
119    log("Waiting for no more RIT\n");
120    TEST_UTIL.waitUntilNoRegionsInTransition(60000);
121    log("Verifying there are " + numRegions + " assigned on cluster\n");
122    regions = HBaseTestingUtility.getAllOnlineRegions(cluster);
123    assertEquals("The assigned regions were not onlined after master"
124        + " switch except for the catalog and namespace tables.",
125          6, regions.size());
126    assertTrue("The table should be in enabled state",
127        cluster.getMaster().getTableStateManager()
128        .isTableState(TableName.valueOf(name.getMethodName()), TableState.State.ENABLED));
129    ht.close();
130    TEST_UTIL.shutdownMiniCluster();
131  }
132
133  private void log(String msg) {
134    LOG.debug("\n\nTRR: " + msg + "\n");
135  }
136}
137