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.util.Bytes;
28  import org.apache.hadoop.hbase.util.Pair;
29  
30  import java.io.IOException;
31  import java.util.List;
32  
33  import org.junit.AfterClass;
34  import org.junit.BeforeClass;
35  import org.junit.Test;
36  
37  import com.google.common.base.Joiner;
38  import org.junit.experimental.categories.Category;
39  
40  import static org.junit.Assert.*;
41  
42  @Category(MediumTests.class)
43  public class TestMaster {
44    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
45    private static final Log LOG = LogFactory.getLog(TestMaster.class);
46    private static final TableName TABLENAME =
47        TableName.valueOf("TestMaster");
48    private static final byte[] FAMILYNAME = Bytes.toBytes("fam");
49    private static HBaseAdmin admin;
50  
51    @BeforeClass
52    public static void beforeAllTests() throws Exception {
53      // Start a cluster of two regionservers.
54      TEST_UTIL.startMiniCluster(2);
55      admin = TEST_UTIL.getHBaseAdmin();
56      TEST_UTIL.getHBaseCluster().getMaster().assignmentManager.initializeHandlerTrackers();
57    }
58  
59    @AfterClass
60    public static void afterAllTests() throws Exception {
61      TEST_UTIL.shutdownMiniCluster();
62    }
63  
64    @Test
65    public void testMasterOpsWhileSplitting() throws Exception {
66      MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
67      HMaster m = cluster.getMaster();
68  
69      HTable ht = TEST_UTIL.createTable(TABLENAME, FAMILYNAME);
70      assertTrue(m.assignmentManager.getZKTable().isEnabledTable(TABLENAME));
71      TEST_UTIL.loadTable(ht, FAMILYNAME, false);
72      ht.close();
73  
74      List<Pair<HRegionInfo, ServerName>> tableRegions =
75        MetaReader.getTableRegionsAndLocations(m.getCatalogTracker(), TABLENAME);
76      LOG.info("Regions after load: " + Joiner.on(',').join(tableRegions));
77      assertEquals(1, tableRegions.size());
78      assertArrayEquals(HConstants.EMPTY_START_ROW,
79          tableRegions.get(0).getFirst().getStartKey());
80      assertArrayEquals(HConstants.EMPTY_END_ROW,
81          tableRegions.get(0).getFirst().getEndKey());
82  
83      // Now trigger a split and stop when the split is in progress
84      LOG.info("Splitting table");
85      TEST_UTIL.getHBaseAdmin().split(TABLENAME.getName());
86      LOG.info("Waiting for split result to be about to open");
87      RegionStates regionStates = m.assignmentManager.getRegionStates();
88      while (regionStates.getRegionsOfTable(TABLENAME).size() <= 1) {
89        Thread.sleep(100);
90      }
91      LOG.info("Making sure we can call getTableRegions while opening");
92      tableRegions = MetaReader.getTableRegionsAndLocations(m.getCatalogTracker(),
93          TABLENAME, false);
94  
95      LOG.info("Regions: " + Joiner.on(',').join(tableRegions));
96      // We have three regions because one is split-in-progress
97      assertEquals(3, tableRegions.size());
98      LOG.info("Making sure we can call getTableRegionClosest while opening");
99      Pair<HRegionInfo, ServerName> pair =
100         m.getTableRegionForRow(TABLENAME, Bytes.toBytes("cde"));
101     LOG.info("Result is: " + pair);
102     Pair<HRegionInfo, ServerName> tableRegionFromName =
103         MetaReader.getRegion(m.getCatalogTracker(),
104             pair.getFirst().getRegionName());
105     assertEquals(tableRegionFromName.getFirst(), pair.getFirst());
106   }
107 
108   @Test
109   public void testMoveRegionWhenNotInitialized() {
110     MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
111     HMaster m = cluster.getMaster();
112     try {
113       m.initialized = false; // fake it, set back later
114       HRegionInfo meta = HRegionInfo.FIRST_META_REGIONINFO;
115       m.move(meta.getEncodedNameAsBytes(), null);
116       fail("Region should not be moved since master is not initialized");
117     } catch (IOException ioe) {
118       assertTrue(ioe instanceof PleaseHoldException);
119     } finally {
120       m.initialized = true;
121     }
122   }
123 
124   @Test
125   public void testMoveThrowsUnknownRegionException() throws IOException {
126     TableName tableName =
127         TableName.valueOf("testMoveThrowsUnknownRegionException");
128     HTableDescriptor htd = new HTableDescriptor(tableName);
129     HColumnDescriptor hcd = new HColumnDescriptor("value");
130     htd.addFamily(hcd);
131 
132     admin.createTable(htd, null);
133     try {
134       HRegionInfo hri = new HRegionInfo(
135         tableName, Bytes.toBytes("A"), Bytes.toBytes("Z"));
136       admin.move(hri.getEncodedNameAsBytes(), null);
137       fail("Region should not be moved since it is fake");
138     } catch (IOException ioe) {
139       assertTrue(ioe instanceof UnknownRegionException);
140     } finally {
141       TEST_UTIL.deleteTable(tableName);
142     }
143   }
144 
145   @Test
146   public void testMoveThrowsPleaseHoldException() throws IOException {
147     byte[] tableName = Bytes.toBytes("testMoveThrowsPleaseHoldException");
148     HMaster master = TEST_UTIL.getMiniHBaseCluster().getMaster();
149     HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(tableName));
150     HColumnDescriptor hcd = new HColumnDescriptor("value");
151     htd.addFamily(hcd);
152 
153     admin.createTable(htd, null);
154     try {
155       List<HRegionInfo> tableRegions = admin.getTableRegions(tableName);
156 
157       master.initialized = false; // fake it, set back later
158       admin.move(tableRegions.get(0).getEncodedNameAsBytes(), null);
159       fail("Region should not be moved since master is not initialized");
160     } catch (IOException ioe) {
161       assertTrue(ioe instanceof PleaseHoldException);
162     } finally {
163       master.initialized = true;
164       TEST_UTIL.deleteTable(tableName);
165     }
166   }
167 }
168