View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.client;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.apache.hadoop.hbase.HBaseTestingUtility;
23  import org.apache.hadoop.hbase.HRegionInfo;
24  import org.apache.hadoop.hbase.HRegionLocation;
25  import org.apache.hadoop.hbase.MiniHBaseCluster;
26  import org.apache.hadoop.hbase.TableName;
27  import org.apache.hadoop.hbase.regionserver.HRegion;
28  import org.apache.hadoop.hbase.regionserver.Region;
29  import org.apache.hadoop.hbase.testclassification.MediumTests;
30  import org.apache.hadoop.hbase.util.Bytes;
31  import org.apache.hadoop.hbase.util.JVMClusterUtil;
32  import org.junit.AfterClass;
33  import org.junit.BeforeClass;
34  import org.junit.Test;
35  import org.junit.experimental.categories.Category;
36  
37  import java.io.IOException;
38  import java.util.List;
39  
40  import static org.junit.Assert.assertEquals;
41  import static org.junit.Assert.assertFalse;
42  import static org.junit.Assert.assertTrue;
43  
44  @Category({MediumTests.class})
45  public class TestSplitOrMergeStatus {
46  
47    private static final Log LOG = LogFactory.getLog(TestSplitOrMergeStatus.class);
48    private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
49    private static byte [] FAMILY = Bytes.toBytes("testFamily");
50  
51    /**
52     * @throws java.lang.Exception
53     */
54    @BeforeClass
55    public static void setUpBeforeClass() throws Exception {
56      TEST_UTIL.getConfiguration().setBoolean("hbase.assignment.usezk", false);
57      TEST_UTIL.startMiniCluster(2);
58    }
59  
60    /**
61     * @throws java.lang.Exception
62     */
63    @AfterClass
64    public static void tearDownAfterClass() throws Exception {
65      TEST_UTIL.shutdownMiniCluster();
66    }
67  
68    @Test
69    public void testSplitSwitch() throws Exception {
70      TableName name = TableName.valueOf("testSplitSwitch");
71      Table t = TEST_UTIL.createTable(name, FAMILY);
72      TEST_UTIL.loadTable(t, FAMILY, false);
73  
74      RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(t.getName());
75      int orignalCount = locator.getAllRegionLocations().size();
76  
77      Admin admin = TEST_UTIL.getHBaseAdmin();
78      initSwitchStatus(admin);
79      boolean[] results = admin.setSplitOrMergeEnabled(false, false, Admin.MasterSwitchType.SPLIT);
80      assertEquals(results.length, 1);
81      assertTrue(results[0]);
82      admin.split(t.getName());
83      int count = waitOnSplitOrMerge(t).size();
84      assertTrue(orignalCount == count);
85  
86      results = admin.setSplitOrMergeEnabled(true, false, Admin.MasterSwitchType.SPLIT);
87      assertEquals(results.length, 1);
88      assertFalse(results[0]);
89      admin.split(t.getName());
90      count = waitOnSplitOrMerge(t).size();
91      assertTrue(orignalCount<count);
92      admin.close();
93    }
94  
95  
96    @Test
97    public void testMergeSwitch() throws Exception {
98      TableName name = TableName.valueOf("testMergeSwitch");
99      Table t = TEST_UTIL.createTable(name, FAMILY);
100     TEST_UTIL.loadTable(t, FAMILY, false);
101 
102     RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(t.getName());
103 
104     Admin admin = TEST_UTIL.getHBaseAdmin();
105     initSwitchStatus(admin);
106     admin.split(t.getName());
107     waitOnSplitOrMerge(t); //Split the table to ensure we have two regions at least.
108 
109     waitForMergable(admin, name);
110     int orignalCount = locator.getAllRegionLocations().size();
111     boolean[] results = admin.setSplitOrMergeEnabled(false, false, Admin.MasterSwitchType.MERGE);
112     assertEquals(results.length, 1);
113     assertTrue(results[0]);
114     List<HRegionInfo> regions = admin.getTableRegions(t.getName());
115     assertTrue(regions.size() > 1);
116     admin.mergeRegions(regions.get(0).getEncodedNameAsBytes(),
117       regions.get(1).getEncodedNameAsBytes(), true);
118     int count = waitOnSplitOrMerge(t).size();
119     assertTrue(orignalCount == count);
120 
121     waitForMergable(admin, name);
122     results = admin.setSplitOrMergeEnabled(true, false, Admin.MasterSwitchType.MERGE);
123     assertEquals(results.length, 1);
124     assertFalse(results[0]);
125     admin.mergeRegions(regions.get(0).getEncodedNameAsBytes(),
126       regions.get(1).getEncodedNameAsBytes(), true);
127     count = waitOnSplitOrMerge(t).size();
128     assertTrue(orignalCount>count);
129     admin.close();
130   }
131 
132   @Test
133   public void testMultiSwitches() throws IOException {
134     Admin admin = TEST_UTIL.getHBaseAdmin();
135     boolean[] switches = admin.setSplitOrMergeEnabled(false, false,
136       Admin.MasterSwitchType.SPLIT, Admin.MasterSwitchType.MERGE);
137     for (boolean s : switches){
138       assertTrue(s);
139     }
140     assertFalse(admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.SPLIT));
141     assertFalse(admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.MERGE));
142     admin.close();
143   }
144 
145   private void initSwitchStatus(Admin admin) throws IOException {
146     if (!admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.SPLIT)) {
147       admin.setSplitOrMergeEnabled(true, false, Admin.MasterSwitchType.SPLIT);
148     }
149     if (!admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.MERGE)) {
150       admin.setSplitOrMergeEnabled(true, false, Admin.MasterSwitchType.MERGE);
151     }
152     assertTrue(admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.SPLIT));
153     assertTrue(admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.MERGE));
154   }
155 
156   private void waitForMergable(Admin admin, TableName t) throws InterruptedException, IOException {
157     // Wait for the Regions to be mergeable
158     MiniHBaseCluster miniCluster = TEST_UTIL.getMiniHBaseCluster();
159     int mergeable = 0;
160     while (mergeable < 2) {
161       Thread.sleep(100);
162       admin.majorCompact(t);
163       mergeable = 0;
164       for (JVMClusterUtil.RegionServerThread regionThread: miniCluster.getRegionServerThreads()) {
165         for (Region region: regionThread.getRegionServer().getOnlineRegions(t)) {
166           mergeable += ((HRegion)region).isMergeable() ? 1 : 0;
167         }
168       }
169     }
170   }
171 
172   /*
173    * Wait on table split.  May return because we waited long enough on the split
174    * and it didn't happen.  Caller should check.
175    * @param t
176    * @return Map of table regions; caller needs to check table actually split.
177    */
178   private List<HRegionLocation> waitOnSplitOrMerge(final Table t)
179     throws IOException {
180     try (RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(t.getName())) {
181       List<HRegionLocation> regions = locator.getAllRegionLocations();
182       int originalCount = regions.size();
183       for (int i = 0; i < TEST_UTIL.getConfiguration().getInt("hbase.test.retries", 10); i++) {
184         Thread.currentThread();
185         try {
186           Thread.sleep(1000);
187         } catch (InterruptedException e) {
188           e.printStackTrace();
189         }
190         regions = locator.getAllRegionLocations();
191         if (regions.size() !=  originalCount)
192           break;
193       }
194       return regions;
195     }
196   }
197 
198 }