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.ClientTests;
30  import org.apache.hadoop.hbase.testclassification.MediumTests;
31  import org.apache.hadoop.hbase.util.Bytes;
32  import org.apache.hadoop.hbase.util.JVMClusterUtil;
33  import org.junit.AfterClass;
34  import org.junit.BeforeClass;
35  import org.junit.Test;
36  import org.junit.experimental.categories.Category;
37  
38  import java.io.IOException;
39  import java.util.List;
40  
41  import static org.junit.Assert.assertEquals;
42  import static org.junit.Assert.assertFalse;
43  import static org.junit.Assert.assertTrue;
44  
45  @Category({MediumTests.class, ClientTests.class})
46  public class TestSplitOrMergeStatus {
47  
48    private static final Log LOG = LogFactory.getLog(TestSplitOrMergeStatus.class);
49    protected final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
50    private static byte [] FAMILY = Bytes.toBytes("testFamily");
51  
52    /**
53     * @throws java.lang.Exception
54     */
55    @BeforeClass
56    public static void setUpBeforeClass() throws Exception {
57      TEST_UTIL.getConfiguration().setBoolean("hbase.assignment.usezk", false);
58      TEST_UTIL.startMiniCluster(2);
59    }
60  
61    /**
62     * @throws java.lang.Exception
63     */
64    @AfterClass
65    public static void tearDownAfterClass() throws Exception {
66      TEST_UTIL.shutdownMiniCluster();
67    }
68  
69    @Test
70    public void testSplitSwitch() throws Exception {
71      TableName name = TableName.valueOf("testSplitSwitch");
72      Table t = TEST_UTIL.createTable(name, FAMILY);
73      TEST_UTIL.loadTable(t, FAMILY, false);
74  
75      RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(t.getName());
76      int orignalCount = locator.getAllRegionLocations().size();
77  
78      Admin admin = TEST_UTIL.getHBaseAdmin();
79      initSwitchStatus(admin);
80      boolean[] results = admin.setSplitOrMergeEnabled(false, false, Admin.MasterSwitchType.SPLIT);
81      assertEquals(results.length, 1);
82      assertTrue(results[0]);
83      admin.split(t.getName());
84      int count = waitOnSplitOrMerge(t).size();
85      assertTrue(orignalCount == count);
86  
87      results = admin.setSplitOrMergeEnabled(true, false, Admin.MasterSwitchType.SPLIT);
88      assertEquals(results.length, 1);
89      assertFalse(results[0]);
90      admin.split(t.getName());
91      count = waitOnSplitOrMerge(t).size();
92      assertTrue(orignalCount<count);
93      admin.close();
94    }
95  
96  
97    @Test
98    public void testMergeSwitch() throws Exception {
99      TableName name = TableName.valueOf("testMergeSwitch");
100     Table t = TEST_UTIL.createTable(name, FAMILY);
101     TEST_UTIL.loadTable(t, FAMILY, false);
102 
103     RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(t.getName());
104 
105     Admin admin = TEST_UTIL.getHBaseAdmin();
106     initSwitchStatus(admin);
107     admin.split(t.getName());
108     waitOnSplitOrMerge(t); //Split the table to ensure we have two regions at least.
109 
110     waitForMergable(admin, name);
111     int orignalCount = locator.getAllRegionLocations().size();
112     boolean[] results = admin.setSplitOrMergeEnabled(false, false, Admin.MasterSwitchType.MERGE);
113     assertEquals(results.length, 1);
114     assertTrue(results[0]);
115     List<HRegionInfo> regions = admin.getTableRegions(t.getName());
116     assertTrue(regions.size() > 1);
117     admin.mergeRegions(regions.get(0).getEncodedNameAsBytes(),
118       regions.get(1).getEncodedNameAsBytes(), true);
119     int count = waitOnSplitOrMerge(t).size();
120     assertTrue(orignalCount == count);
121 
122     waitForMergable(admin, name);
123     results = admin.setSplitOrMergeEnabled(true, false, Admin.MasterSwitchType.MERGE);
124     assertEquals(results.length, 1);
125     assertFalse(results[0]);
126     admin.mergeRegions(regions.get(0).getEncodedNameAsBytes(),
127       regions.get(1).getEncodedNameAsBytes(), true);
128     count = waitOnSplitOrMerge(t).size();
129     assertTrue(orignalCount>count);
130     admin.close();
131   }
132 
133   @Test
134   public void testMultiSwitches() throws IOException {
135     Admin admin = TEST_UTIL.getHBaseAdmin();
136     boolean[] switches = admin.setSplitOrMergeEnabled(false, false,
137       Admin.MasterSwitchType.SPLIT, Admin.MasterSwitchType.MERGE);
138     for (boolean s : switches){
139       assertTrue(s);
140     }
141     assertFalse(admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.SPLIT));
142     assertFalse(admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.MERGE));
143     admin.close();
144   }
145 
146   private void initSwitchStatus(Admin admin) throws IOException {
147     if (!admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.SPLIT)) {
148       admin.setSplitOrMergeEnabled(true, false, Admin.MasterSwitchType.SPLIT);
149     }
150     if (!admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.MERGE)) {
151       admin.setSplitOrMergeEnabled(true, false, Admin.MasterSwitchType.MERGE);
152     }
153     assertTrue(admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.SPLIT));
154     assertTrue(admin.isSplitOrMergeEnabled(Admin.MasterSwitchType.MERGE));
155   }
156 
157   private void waitForMergable(Admin admin, TableName t) throws InterruptedException, IOException {
158     // Wait for the Regions to be mergeable
159     MiniHBaseCluster miniCluster = TEST_UTIL.getMiniHBaseCluster();
160     int mergeable = 0;
161     while (mergeable < 2) {
162       Thread.sleep(100);
163       admin.majorCompact(t);
164       mergeable = 0;
165       for (JVMClusterUtil.RegionServerThread regionThread: miniCluster.getRegionServerThreads()) {
166         for (Region region: regionThread.getRegionServer().getOnlineRegions(t)) {
167           mergeable += ((HRegion)region).isMergeable() ? 1 : 0;
168         }
169       }
170     }
171   }
172 
173   /*
174    * Wait on table split.  May return because we waited long enough on the split
175    * and it didn't happen.  Caller should check.
176    * @param t
177    * @return Map of table regions; caller needs to check table actually split.
178    */
179   private List<HRegionLocation> waitOnSplitOrMerge(final Table t)
180     throws IOException {
181     try (RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(t.getName())) {
182       List<HRegionLocation> regions = locator.getAllRegionLocations();
183       int originalCount = regions.size();
184       for (int i = 0; i < TEST_UTIL.getConfiguration().getInt("hbase.test.retries", 10); i++) {
185         Thread.currentThread();
186         try {
187           Thread.sleep(1000);
188         } catch (InterruptedException e) {
189           e.printStackTrace();
190         }
191         regions = locator.getAllRegionLocations();
192         if (regions.size() !=  originalCount)
193           break;
194       }
195       return regions;
196     }
197   }
198 
199 }