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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org
.apache
.hadoop
.hbase
.client
;
20 import static org
.junit
.Assert
.assertEquals
;
21 import static org
.junit
.Assert
.assertFalse
;
22 import static org
.junit
.Assert
.assertTrue
;
23 import static org
.junit
.Assert
.fail
;
25 import java
.io
.IOException
;
26 import java
.util
.List
;
27 import java
.util
.concurrent
.ExecutionException
;
28 import java
.util
.concurrent
.Future
;
29 import java
.util
.concurrent
.TimeUnit
;
31 import org
.apache
.hadoop
.hbase
.DoNotRetryIOException
;
32 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
33 import org
.apache
.hadoop
.hbase
.HBaseTestingUtil
;
34 import org
.apache
.hadoop
.hbase
.ServerName
;
35 import org
.apache
.hadoop
.hbase
.TableName
;
36 import org
.apache
.hadoop
.hbase
.master
.assignment
.AssignmentTestingUtil
;
37 import org
.apache
.hadoop
.hbase
.master
.assignment
.SplitTableRegionProcedure
;
38 import org
.apache
.hadoop
.hbase
.master
.procedure
.DeleteTableProcedure
;
39 import org
.apache
.hadoop
.hbase
.master
.procedure
.DisableTableProcedure
;
40 import org
.apache
.hadoop
.hbase
.master
.procedure
.MasterProcedureEnv
;
41 import org
.apache
.hadoop
.hbase
.procedure2
.ProcedureExecutor
;
42 import org
.apache
.hadoop
.hbase
.procedure2
.ProcedureTestingUtility
;
43 import org
.apache
.hadoop
.hbase
.testclassification
.ClientTests
;
44 import org
.apache
.hadoop
.hbase
.testclassification
.MediumTests
;
45 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
46 import org
.apache
.hadoop
.hbase
.util
.Threads
;
47 import org
.junit
.After
;
48 import org
.junit
.Before
;
49 import org
.junit
.ClassRule
;
50 import org
.junit
.Ignore
;
51 import org
.junit
.Rule
;
52 import org
.junit
.Test
;
53 import org
.junit
.experimental
.categories
.Category
;
54 import org
.junit
.rules
.TestName
;
56 @Category({MediumTests
.class, ClientTests
.class})
57 public class TestSplitOrMergeStatus
{
60 public static final HBaseClassTestRule CLASS_RULE
=
61 HBaseClassTestRule
.forClass(TestSplitOrMergeStatus
.class);
63 private final static HBaseTestingUtil TEST_UTIL
= new HBaseTestingUtil();
64 private static byte [] FAMILY
= Bytes
.toBytes("testFamily");
67 public TestName name
= new TestName();
70 public void setUp() throws Exception
{
71 TEST_UTIL
.startMiniCluster(2);
75 public void tearDown() throws Exception
{
76 TEST_UTIL
.shutdownMiniCluster();
80 public void testSplitSwitch() throws Exception
{
81 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
82 Table t
= TEST_UTIL
.createTable(tableName
, FAMILY
);
83 TEST_UTIL
.loadTable(t
, FAMILY
, false);
85 RegionLocator locator
= TEST_UTIL
.getConnection().getRegionLocator(t
.getName());
86 int originalCount
= locator
.getAllRegionLocations().size();
88 Admin admin
= TEST_UTIL
.getAdmin();
89 initSwitchStatus(admin
);
90 assertTrue(admin
.splitSwitch(false, false));
92 admin
.split(t
.getName());
93 fail("Shouldn't get here");
94 } catch (DoNotRetryIOException dnioe
) {
97 int count
= admin
.getRegions(tableName
).size();
98 assertTrue(originalCount
== count
);
99 assertFalse(admin
.splitSwitch(true, false));
100 admin
.split(t
.getName());
101 while ((count
= admin
.getRegions(tableName
).size()) == originalCount
) {
104 count
= admin
.getRegions(tableName
).size();
105 assertTrue(originalCount
< count
);
111 public void testMergeSwitch() throws Exception
{
112 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
113 Table t
= TEST_UTIL
.createTable(tableName
, FAMILY
);
114 TEST_UTIL
.loadTable(t
, FAMILY
, false);
116 Admin admin
= TEST_UTIL
.getAdmin();
117 int originalCount
= admin
.getRegions(tableName
).size();
118 initSwitchStatus(admin
);
119 admin
.split(t
.getName());
120 int postSplitCount
= -1;
121 while ((postSplitCount
= admin
.getRegions(tableName
).size()) == originalCount
) {
124 assertTrue("originalCount=" + originalCount
+ ", newCount=" + postSplitCount
,
125 originalCount
!= postSplitCount
);
127 // Merge switch is off so merge should NOT succeed.
128 boolean result
= admin
.mergeSwitch(false, false);
130 List
<RegionInfo
> regions
= admin
.getRegions(t
.getName());
131 assertTrue(regions
.size() > 1);
132 Future
<?
> f
= admin
.mergeRegionsAsync(regions
.get(0).getEncodedNameAsBytes(),
133 regions
.get(1).getEncodedNameAsBytes(), true);
135 f
.get(10, TimeUnit
.SECONDS
);
136 fail("Should not get here.");
137 } catch (ExecutionException ee
) {
140 int count
= admin
.getRegions(tableName
).size();
141 assertTrue("newCount=" + postSplitCount
+ ", count=" + count
, postSplitCount
== count
);
143 result
= admin
.mergeSwitch(true, false);
144 regions
= admin
.getRegions(t
.getName());
146 f
= admin
.mergeRegionsAsync(regions
.get(0).getEncodedNameAsBytes(),
147 regions
.get(1).getEncodedNameAsBytes(), true);
148 f
.get(10, TimeUnit
.SECONDS
);
149 count
= admin
.getRegions(tableName
).size();
150 assertTrue((postSplitCount
/ 2 /*Merge*/) == count
);
155 public void testMultiSwitches() throws IOException
{
156 Admin admin
= TEST_UTIL
.getAdmin();
157 assertTrue(admin
.splitSwitch(false, false));
158 assertTrue(admin
.mergeSwitch(false, false));
160 assertFalse(admin
.isSplitEnabled());
161 assertFalse(admin
.isMergeEnabled());
166 public void testSplitRegionReplicaRitRecovery() throws Exception
{
167 int startRowNum
= 11;
169 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
170 final ProcedureExecutor
<MasterProcedureEnv
> procExec
= getMasterProcedureExecutor();
171 TEST_UTIL
.getAdmin().createTable(TableDescriptorBuilder
.newBuilder(tableName
)
172 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(FAMILY
)).setRegionReplication(2).build());
173 TEST_UTIL
.waitUntilAllRegionsAssigned(tableName
);
174 ServerName serverName
=
175 RegionReplicaTestHelper
.getRSCarryingReplica(TEST_UTIL
, tableName
, 1).get();
176 List
<RegionInfo
> regions
= TEST_UTIL
.getAdmin().getRegions(tableName
);
177 insertData(tableName
, startRowNum
, rowCount
);
178 int splitRowNum
= startRowNum
+ rowCount
/ 2;
179 byte[] splitKey
= Bytes
.toBytes("" + splitRowNum
);
180 // Split region of the table
181 long procId
= procExec
.submitProcedure(
182 new SplitTableRegionProcedure(procExec
.getEnvironment(), regions
.get(0), splitKey
));
183 // Wait the completion
184 ProcedureTestingUtility
.waitProcedure(procExec
, procId
);
186 long procId1
= procExec
187 .submitProcedure(new DisableTableProcedure(procExec
.getEnvironment(), tableName
, false));
188 // Wait the completion
189 ProcedureTestingUtility
.waitProcedure(procExec
, procId1
);
192 procExec
.submitProcedure(new DeleteTableProcedure(procExec
.getEnvironment(), tableName
));
193 // Wait the completion
194 ProcedureTestingUtility
.waitProcedure(procExec
, procId2
);
195 AssignmentTestingUtil
.killRs(TEST_UTIL
, serverName
);
196 Threads
.sleepWithoutInterrupt(5000);
197 boolean hasRegionsInTransition
= TEST_UTIL
.getMiniHBaseCluster().getMaster()
198 .getAssignmentManager().getRegionStates().hasRegionsInTransition();
199 assertEquals(false, hasRegionsInTransition
);
202 private ProcedureExecutor
<MasterProcedureEnv
> getMasterProcedureExecutor() {
203 return TEST_UTIL
.getHBaseCluster().getMaster().getMasterProcedureExecutor();
206 private void insertData(final TableName tableName
, int startRow
, int rowCount
)
208 Table t
= TEST_UTIL
.getConnection().getTable(tableName
);
210 for (int i
= 0; i
< rowCount
; i
++) {
211 p
= new Put(Bytes
.toBytes("" + (startRow
+ i
)));
212 p
.addColumn(FAMILY
, Bytes
.toBytes("q1"), Bytes
.toBytes(i
));
217 private void initSwitchStatus(Admin admin
) throws IOException
{
218 if (!admin
.isSplitEnabled()) {
219 admin
.splitSwitch(true, false);
221 if (!admin
.isMergeEnabled()) {
222 admin
.mergeSwitch(true, false);
224 assertTrue(admin
.isSplitEnabled());
225 assertTrue(admin
.isMergeEnabled());