1   /**
2    * Copyright 2011 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.master;
21  
22  import static org.junit.Assert.assertEquals;
23  
24  import java.io.IOException;
25  import java.util.List;
26  import java.util.NavigableSet;
27  import java.util.TreeSet;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.hadoop.conf.Configuration;
32  import org.apache.hadoop.hbase.HBaseConfiguration;
33  import org.apache.hadoop.hbase.HBaseTestingUtility;
34  import org.apache.hadoop.hbase.HRegionInfo;
35  import org.apache.hadoop.hbase.MiniHBaseCluster;
36  import org.apache.hadoop.hbase.client.HTable;
37  import org.apache.hadoop.hbase.util.Bytes;
38  import org.apache.hadoop.hbase.util.JVMClusterUtil.MasterThread;
39  import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
40  import org.apache.hadoop.hbase.zookeeper.ZKAssign;
41  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
42  import org.apache.zookeeper.KeeperException;
43  import org.junit.Test;
44  
45  public class TestMasterRestartAfterDisablingTable {
46  
47    private static final Log LOG = LogFactory.getLog(TestMasterRestartAfterDisablingTable.class);
48  
49    @Test
50    public void testForCheckingIfEnableAndDisableWorksFineAfterSwitch()
51        throws Exception {
52      final int NUM_MASTERS = 2;
53      final int NUM_RS = 1;
54      final int NUM_REGIONS_TO_CREATE = 4;
55  
56      // Start the cluster
57      log("Starting cluster");
58      Configuration conf = HBaseConfiguration.create();
59      conf.setInt("hbase.master.assignment.timeoutmonitor.period", 2000);
60      conf.setInt("hbase.master.assignment.timeoutmonitor.timeout", 5000);
61      HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(conf);
62      TEST_UTIL.startMiniCluster(NUM_MASTERS, NUM_RS);
63      MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
64      log("Waiting for active/ready master");
65      cluster.waitForActiveAndReadyMaster();
66      ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf, "testmasterRestart", null);
67      HMaster master = cluster.getMaster();
68  
69      // Create a table with regions
70      byte[] table = Bytes.toBytes("tableRestart");
71      byte[] family = Bytes.toBytes("family");
72      log("Creating table with " + NUM_REGIONS_TO_CREATE + " regions");
73      HTable ht = TEST_UTIL.createTable(table, family);
74      int numRegions = TEST_UTIL.createMultiRegions(conf, ht, family,
75          NUM_REGIONS_TO_CREATE);
76      numRegions += 2; // catalogs
77      log("Waiting for no more RIT\n");
78      blockUntilNoRIT(zkw, master);
79      log("Disabling table\n");
80      TEST_UTIL.getHBaseAdmin().disableTable(table);
81  
82      NavigableSet<String> regions = getAllOnlineRegions(cluster);
83      assertEquals(
84          "The number of regions for the table tableRestart should be 0 and only"
85              + "the catalog tables should be present.", 2, regions.size());
86  
87      List<MasterThread> masterThreads = cluster.getMasterThreads();
88      MasterThread activeMaster = null;
89      if (masterThreads.get(0).getMaster().isActiveMaster()) {
90        activeMaster = masterThreads.get(0);
91      } else {
92        activeMaster = masterThreads.get(1);
93      }
94      activeMaster.getMaster().stop(
95          "stopping the active master so that the backup can become active");
96      cluster.hbaseCluster.waitOnMaster(activeMaster);
97      cluster.waitForActiveAndReadyMaster();
98  
99      log("Enabling table\n");
100     TEST_UTIL.getHBaseAdmin().enableTable(table);
101     log("Waiting for no more RIT\n");
102     blockUntilNoRIT(zkw, master);
103     log("Verifying there are " + numRegions + " assigned on cluster\n");
104     regions = getAllOnlineRegions(cluster);
105     assertEquals(
106         "The assigned regions were not onlined after master switch except for the catalog tables.",
107         6, regions.size());
108   }
109 
110   private void log(String msg) {
111     LOG.debug("\n\nTRR: " + msg + "\n");
112   }
113 
114   private void blockUntilNoRIT(ZooKeeperWatcher zkw, HMaster master)
115       throws KeeperException, InterruptedException {
116     ZKAssign.blockUntilNoRIT(zkw);
117     master.assignmentManager.waitUntilNoRegionsInTransition(60000);
118   }
119 
120   private NavigableSet<String> getAllOnlineRegions(MiniHBaseCluster cluster)
121       throws IOException {
122     NavigableSet<String> online = new TreeSet<String>();
123     for (RegionServerThread rst : cluster.getLiveRegionServerThreads()) {
124       for (HRegionInfo region : rst.getRegionServer().getOnlineRegions()) {
125         online.add(region.getRegionNameAsString());
126       }
127     }
128     return online;
129   }
130 }