View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.master;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.hadoop.hbase.*;
24  import org.apache.hadoop.hbase.catalog.MetaReader;
25  import org.apache.hadoop.hbase.client.HBaseAdmin;
26  import org.apache.hadoop.hbase.client.HTable;
27  import org.apache.hadoop.hbase.testclassification.MediumTests;
28  import org.apache.hadoop.hbase.util.Bytes;
29  import org.apache.hadoop.hbase.util.Pair;
30  
31  import java.io.IOException;
32  import java.util.List;
33  
34  import org.junit.AfterClass;
35  import org.junit.BeforeClass;
36  import org.junit.Test;
37  
38  import com.google.common.base.Joiner;
39  import org.junit.experimental.categories.Category;
40  
41  import static org.junit.Assert.*;
42  
43  @Category(MediumTests.class)
44  public class TestMaster {
45    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
46    private static final Log LOG = LogFactory.getLog(TestMaster.class);
47    private static final TableName TABLENAME =
48        TableName.valueOf("TestMaster");
49    private static final byte[] FAMILYNAME = Bytes.toBytes("fam");
50    private static HBaseAdmin admin;
51  
52    @BeforeClass
53    public static void beforeAllTests() throws Exception {
54      // Start a cluster of two regionservers.
55      TEST_UTIL.startMiniCluster(2);
56      admin = TEST_UTIL.getHBaseAdmin();
57      TEST_UTIL.getHBaseCluster().getMaster().assignmentManager.initializeHandlerTrackers();
58    }
59  
60    @AfterClass
61    public static void afterAllTests() throws Exception {
62      TEST_UTIL.shutdownMiniCluster();
63    }
64  
65    @Test
66    public void testMasterOpsWhileSplitting() throws Exception {
67      MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
68      HMaster m = cluster.getMaster();
69  
70      HTable ht = TEST_UTIL.createTable(TABLENAME, FAMILYNAME);
71      assertTrue(m.assignmentManager.getZKTable().isEnabledTable(TABLENAME));
72      TEST_UTIL.loadTable(ht, FAMILYNAME, false);
73      ht.close();
74  
75      List<Pair<HRegionInfo, ServerName>> tableRegions =
76        MetaReader.getTableRegionsAndLocations(m.getCatalogTracker(), TABLENAME);
77      LOG.info("Regions after load: " + Joiner.on(',').join(tableRegions));
78      assertEquals(1, tableRegions.size());
79      assertArrayEquals(HConstants.EMPTY_START_ROW,
80          tableRegions.get(0).getFirst().getStartKey());
81      assertArrayEquals(HConstants.EMPTY_END_ROW,
82          tableRegions.get(0).getFirst().getEndKey());
83  
84      // Now trigger a split and stop when the split is in progress
85      LOG.info("Splitting table");
86      TEST_UTIL.getHBaseAdmin().split(TABLENAME.getName());
87      LOG.info("Waiting for split result to be about to open");
88      RegionStates regionStates = m.assignmentManager.getRegionStates();
89      while (regionStates.getRegionsOfTable(TABLENAME).size() <= 1) {
90        Thread.sleep(100);
91      }
92      LOG.info("Making sure we can call getTableRegions while opening");
93      tableRegions = MetaReader.getTableRegionsAndLocations(m.getCatalogTracker(),
94          TABLENAME, false);
95  
96      LOG.info("Regions: " + Joiner.on(',').join(tableRegions));
97      // We have three regions because one is split-in-progress
98      assertEquals(3, tableRegions.size());
99      LOG.info("Making sure we can call getTableRegionClosest while opening");
100     Pair<HRegionInfo, ServerName> pair =
101         m.getTableRegionForRow(TABLENAME, Bytes.toBytes("cde"));
102     LOG.info("Result is: " + pair);
103     Pair<HRegionInfo, ServerName> tableRegionFromName =
104         MetaReader.getRegion(m.getCatalogTracker(),
105             pair.getFirst().getRegionName());
106     assertEquals(tableRegionFromName.getFirst(), pair.getFirst());
107   }
108 
109   @Test
110   public void testMoveRegionWhenNotInitialized() {
111     MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
112     HMaster m = cluster.getMaster();
113     try {
114       m.initialized = false; // fake it, set back later
115       HRegionInfo meta = HRegionInfo.FIRST_META_REGIONINFO;
116       m.move(meta.getEncodedNameAsBytes(), null);
117       fail("Region should not be moved since master is not initialized");
118     } catch (IOException ioe) {
119       assertTrue(ioe instanceof PleaseHoldException);
120     } finally {
121       m.initialized = true;
122     }
123   }
124 
125   @Test
126   public void testMoveThrowsUnknownRegionException() throws IOException {
127     TableName tableName =
128         TableName.valueOf("testMoveThrowsUnknownRegionException");
129     HTableDescriptor htd = new HTableDescriptor(tableName);
130     HColumnDescriptor hcd = new HColumnDescriptor("value");
131     htd.addFamily(hcd);
132 
133     admin.createTable(htd, null);
134     try {
135       HRegionInfo hri = new HRegionInfo(
136         tableName, Bytes.toBytes("A"), Bytes.toBytes("Z"));
137       admin.move(hri.getEncodedNameAsBytes(), null);
138       fail("Region should not be moved since it is fake");
139     } catch (IOException ioe) {
140       assertTrue(ioe instanceof UnknownRegionException);
141     } finally {
142       TEST_UTIL.deleteTable(tableName);
143     }
144   }
145 
146   @Test
147   public void testMoveThrowsPleaseHoldException() throws IOException {
148     byte[] tableName = Bytes.toBytes("testMoveThrowsPleaseHoldException");
149     HMaster master = TEST_UTIL.getMiniHBaseCluster().getMaster();
150     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(tableName));
151     HColumnDescriptor hcd = new HColumnDescriptor("value");
152     htd.addFamily(hcd);
153 
154     admin.createTable(htd, null);
155     try {
156       List<HRegionInfo> tableRegions = admin.getTableRegions(tableName);
157 
158       master.initialized = false; // fake it, set back later
159       admin.move(tableRegions.get(0).getEncodedNameAsBytes(), null);
160       fail("Region should not be moved since master is not initialized");
161     } catch (IOException ioe) {
162       assertTrue(ioe instanceof PleaseHoldException);
163     } finally {
164       master.initialized = true;
165       TEST_UTIL.deleteTable(tableName);
166     }
167   }
168 }
169