1   /**
2    * Copyright 2010 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 org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.hbase.HBaseTestingUtility;
25  import org.apache.hadoop.hbase.HColumnDescriptor;
26  import org.apache.hadoop.hbase.HMsg;
27  import org.apache.hadoop.hbase.HServerInfo;
28  import org.apache.hadoop.hbase.HTableDescriptor;
29  import org.apache.hadoop.hbase.MiniHBaseCluster;
30  import org.apache.hadoop.hbase.client.HBaseAdmin;
31  import org.apache.hadoop.hbase.client.HTable;
32  import org.apache.hadoop.hbase.util.Bytes;
33  import org.junit.AfterClass;
34  import org.junit.BeforeClass;
35  import org.junit.Test;
36  import static org.junit.Assert.fail;
37  import static org.junit.Assert.assertEquals;
38  
39  import java.io.IOException;
40  
41  /**
42   * Disabling is tricky. This class tests how the Master behaves during those
43   */
44  public class TestMasterWithDisabling {
45  
46    private static final Log LOG = LogFactory.getLog(TestMasterWithDisabling.class);
47    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
48    private static final byte[] TABLENAME = Bytes.toBytes("disabling");
49    private static final byte[] FAMILYNAME = Bytes.toBytes("fam");
50  
51    @BeforeClass
52    public static void beforeAllTests() throws Exception {
53      // Start a cluster of two regionservers.
54      TEST_UTIL.startMiniCluster(2);
55    }
56  
57    @AfterClass
58    public static void afterAllTests() throws IOException {
59      TEST_UTIL.shutdownMiniCluster();
60    }
61  
62    @Test
63    public void testDisableBetweenSplit() throws IOException {
64      // Table that splits like crazy
65      HTableDescriptor htd = new HTableDescriptor(TABLENAME);
66      htd.setMaxFileSize(1024);
67      htd.setMemStoreFlushSize(1024);
68      HColumnDescriptor hcd = new HColumnDescriptor(FAMILYNAME);
69      htd.addFamily(hcd);
70      TEST_UTIL.getHBaseAdmin().createTable(htd);
71      HTable t = new HTable(TEST_UTIL.getConfiguration(), TABLENAME);
72      HBase2515Listener list = new HBase2515Listener(TEST_UTIL.getHBaseAdmin());
73      MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
74      HMaster m = cluster.getMaster();
75      m.getRegionServerOperationQueue().
76        registerRegionServerOperationListener(list);
77      try {
78        TEST_UTIL.loadTable(t, FAMILYNAME);
79      } catch (IOException ex) {
80        // We disable the table during a split, we will end up here
81        LOG.info("Expected", ex);
82      }
83      // Check that there's no region in flight, HBASE-2515
84      assertEquals(0,cluster.getMaster().
85          getClusterStatus().getRegionsInTransition().size());
86    }
87  
88    /**
89     * Simple listener that simulates a very long processing of a split. When
90     * we catch it, we first disable the table then let the processing go forward
91     */
92    static class HBase2515Listener implements RegionServerOperationListener {
93      HBaseAdmin admin;
94  
95      public HBase2515Listener(HBaseAdmin admin) {
96        this.admin = admin;
97      }
98  
99      @Override
100     public boolean process(HServerInfo serverInfo, HMsg incomingMsg) {
101       if (!incomingMsg.isType(HMsg.Type.MSG_REPORT_SPLIT_INCLUDES_DAUGHTERS)) {
102         return true;
103       }
104       try {
105         LOG.info("Disabling table");
106         admin.disableTable(TABLENAME);
107       } catch (IOException e) {
108         LOG.warn(e);
109         fail("Disable should always work");
110       }
111       return true;
112     }
113 
114     @Override
115     public boolean process(RegionServerOperation op) throws IOException {
116       return true;
117     }
118 
119     @Override
120     public void processed(RegionServerOperation op) {
121     }
122   }
123 
124 }