HBASE-24942 MergeTableRegionsProcedure should not call clean merge region (#2301)
[hbase.git] / hbase-server / src / test / java / org / apache / hadoop / hbase / client / TestAsyncRegionAdminApi2.java
blobcc680266c105540938f09b88034affa7bbc45046
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
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.apache.hadoop.hbase.TableName.META_TABLE_NAME;
21 import static org.hamcrest.CoreMatchers.instanceOf;
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertThat;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.List;
32 import java.util.concurrent.ExecutionException;
33 import java.util.stream.Collectors;
34 import org.apache.hadoop.hbase.ClientMetaTableAccessor;
35 import org.apache.hadoop.hbase.HBaseClassTestRule;
36 import org.apache.hadoop.hbase.HConstants;
37 import org.apache.hadoop.hbase.HRegionLocation;
38 import org.apache.hadoop.hbase.TableName;
39 import org.apache.hadoop.hbase.master.CatalogJanitor;
40 import org.apache.hadoop.hbase.master.HMaster;
41 import org.apache.hadoop.hbase.testclassification.ClientTests;
42 import org.apache.hadoop.hbase.testclassification.LargeTests;
43 import org.apache.hadoop.hbase.util.Bytes;
44 import org.apache.hadoop.hbase.util.Threads;
45 import org.junit.ClassRule;
46 import org.junit.Ignore;
47 import org.junit.Test;
48 import org.junit.experimental.categories.Category;
49 import org.junit.runner.RunWith;
50 import org.junit.runners.Parameterized;
52 /**
53 * Class to test asynchronous region admin operations.
54 * @see TestAsyncRegionAdminApi This test and it used to be joined it was taking longer than our
55 * ten minute timeout so they were split.
57 @RunWith(Parameterized.class)
58 @Category({ LargeTests.class, ClientTests.class })
59 public class TestAsyncRegionAdminApi2 extends TestAsyncAdminBase {
61 @ClassRule
62 public static final HBaseClassTestRule CLASS_RULE =
63 HBaseClassTestRule.forClass(TestAsyncRegionAdminApi2.class);
65 @Test
66 public void testGetRegionLocation() throws Exception {
67 RawAsyncHBaseAdmin rawAdmin = (RawAsyncHBaseAdmin) ASYNC_CONN.getAdmin();
68 TEST_UTIL.createMultiRegionTable(tableName, HConstants.CATALOG_FAMILY);
69 AsyncTableRegionLocator locator = ASYNC_CONN.getRegionLocator(tableName);
70 HRegionLocation regionLocation = locator.getRegionLocation(Bytes.toBytes("mmm")).get();
71 RegionInfo region = regionLocation.getRegion();
72 byte[] regionName = regionLocation.getRegion().getRegionName();
73 HRegionLocation location = rawAdmin.getRegionLocation(regionName).get();
74 assertTrue(Bytes.equals(regionName, location.getRegion().getRegionName()));
75 location = rawAdmin.getRegionLocation(region.getEncodedNameAsBytes()).get();
76 assertTrue(Bytes.equals(regionName, location.getRegion().getRegionName()));
79 @Test
80 public void testSplitSwitch() throws Exception {
81 createTableWithDefaultConf(tableName);
82 byte[][] families = {FAMILY};
83 final int rows = 10000;
84 TestAsyncRegionAdminApi.loadData(tableName, families, rows);
86 AsyncTable<AdvancedScanResultConsumer> metaTable = ASYNC_CONN.getTable(META_TABLE_NAME);
87 List<HRegionLocation> regionLocations =
88 ClientMetaTableAccessor.getTableHRegionLocations(metaTable, tableName).get();
89 int originalCount = regionLocations.size();
91 initSplitMergeSwitch();
92 assertTrue(admin.splitSwitch(false).get());
93 try {
94 admin.split(tableName, Bytes.toBytes(rows / 2)).join();
95 } catch (Exception e) {
96 //Expected
98 int count = admin.getRegions(tableName).get().size();
99 assertTrue(originalCount == count);
101 assertFalse(admin.splitSwitch(true).get());
102 admin.split(tableName).join();
103 while ((count = admin.getRegions(tableName).get().size()) == originalCount) {
104 Threads.sleep(100);
106 assertTrue(originalCount < count);
109 @Test
110 @Ignore
111 // It was ignored in TestSplitOrMergeStatus, too
112 public void testMergeSwitch() throws Exception {
113 createTableWithDefaultConf(tableName);
114 byte[][] families = {FAMILY};
115 TestAsyncRegionAdminApi.loadData(tableName, families, 1000);
117 AsyncTable<AdvancedScanResultConsumer> metaTable = ASYNC_CONN.getTable(META_TABLE_NAME);
118 List<HRegionLocation> regionLocations =
119 ClientMetaTableAccessor.getTableHRegionLocations(metaTable, tableName).get();
120 int originalCount = regionLocations.size();
122 initSplitMergeSwitch();
123 admin.split(tableName).join();
124 int postSplitCount = originalCount;
125 while ((postSplitCount = admin.getRegions(tableName).get().size()) == originalCount) {
126 Threads.sleep(100);
128 assertTrue("originalCount=" + originalCount + ", postSplitCount=" + postSplitCount,
129 originalCount != postSplitCount);
131 // Merge switch is off so merge should NOT succeed.
132 assertTrue(admin.mergeSwitch(false).get());
133 List<RegionInfo> regions = admin.getRegions(tableName).get();
134 assertTrue(regions.size() > 1);
135 admin.mergeRegions(regions.get(0).getRegionName(), regions.get(1).getRegionName(), true).join();
136 int count = admin.getRegions(tableName).get().size();
137 assertTrue("postSplitCount=" + postSplitCount + ", count=" + count, postSplitCount == count);
139 // Merge switch is on so merge should succeed.
140 assertFalse(admin.mergeSwitch(true).get());
141 admin.mergeRegions(regions.get(0).getRegionName(), regions.get(1).getRegionName(), true).join();
142 count = admin.getRegions(tableName).get().size();
143 assertTrue((postSplitCount / 2) == count);
146 private void initSplitMergeSwitch() throws Exception {
147 if (!admin.isSplitEnabled().get()) {
148 admin.splitSwitch(true).get();
150 if (!admin.isMergeEnabled().get()) {
151 admin.mergeSwitch(true).get();
153 assertTrue(admin.isSplitEnabled().get());
154 assertTrue(admin.isMergeEnabled().get());
157 @Test
158 public void testMergeRegions() throws Exception {
159 byte[][] splitRows = new byte[][]{Bytes.toBytes("3"), Bytes.toBytes("6")};
160 createTableWithDefaultConf(tableName, splitRows);
162 AsyncTable<AdvancedScanResultConsumer> metaTable = ASYNC_CONN.getTable(META_TABLE_NAME);
163 List<HRegionLocation> regionLocations = ClientMetaTableAccessor
164 .getTableHRegionLocations(metaTable, tableName).get();
165 RegionInfo regionA;
166 RegionInfo regionB;
167 RegionInfo regionC;
168 RegionInfo mergedChildRegion = null;
170 // merge with full name
171 assertEquals(3, regionLocations.size());
172 regionA = regionLocations.get(0).getRegion();
173 regionB = regionLocations.get(1).getRegion();
174 regionC = regionLocations.get(2).getRegion();
175 admin.mergeRegions(regionA.getRegionName(), regionB.getRegionName(), false).get();
177 regionLocations = ClientMetaTableAccessor
178 .getTableHRegionLocations(metaTable, tableName).get();
180 assertEquals(2, regionLocations.size());
181 for (HRegionLocation rl : regionLocations) {
182 if (regionC.compareTo(rl.getRegion()) != 0) {
183 mergedChildRegion = rl.getRegion();
184 break;
188 assertNotNull(mergedChildRegion);
189 // Need to wait GC for merged child region is done.
190 HMaster services = TEST_UTIL.getHBaseCluster().getMaster();
191 CatalogJanitor cj = services.getCatalogJanitor();
192 assertTrue(cj.scan() > 0);
193 // Wait until all procedures settled down
194 while (!services.getMasterProcedureExecutor().getActiveProcIds().isEmpty()) {
195 Thread.sleep(200);
197 // merge with encoded name
198 admin.mergeRegions(regionC.getRegionName(), mergedChildRegion.getRegionName(),
199 false).get();
201 regionLocations = ClientMetaTableAccessor
202 .getTableHRegionLocations(metaTable, tableName).get();
203 assertEquals(1, regionLocations.size());
206 @Test
207 public void testMergeRegionsInvalidRegionCount() throws Exception {
208 byte[][] splitRows = new byte[][] { Bytes.toBytes("3"), Bytes.toBytes("6") };
209 createTableWithDefaultConf(tableName, splitRows);
210 List<RegionInfo> regions = admin.getRegions(tableName).join();
211 // 0
212 try {
213 admin.mergeRegions(Collections.emptyList(), false).get();
214 fail();
215 } catch (ExecutionException e) {
216 // expected
217 assertThat(e.getCause(), instanceOf(IllegalArgumentException.class));
219 // 1
220 try {
221 admin.mergeRegions(regions.stream().limit(1).map(RegionInfo::getEncodedNameAsBytes)
222 .collect(Collectors.toList()), false).get();
223 fail();
224 } catch (ExecutionException e) {
225 // expected
226 assertThat(e.getCause(), instanceOf(IllegalArgumentException.class));
230 @Test
231 public void testSplitTable() throws Exception {
232 initSplitMergeSwitch();
233 splitTest(TableName.valueOf("testSplitTable"), 3000, false, null);
234 splitTest(TableName.valueOf("testSplitTableWithSplitPoint"), 3000, false, Bytes.toBytes("3"));
235 splitTest(TableName.valueOf("testSplitTableRegion"), 3000, true, null);
236 splitTest(TableName.valueOf("testSplitTableRegionWithSplitPoint2"), 3000, true, Bytes.toBytes("3"));
239 private void
240 splitTest(TableName tableName, int rowCount, boolean isSplitRegion, byte[] splitPoint)
241 throws Exception {
242 // create table
243 createTableWithDefaultConf(tableName);
245 AsyncTable<AdvancedScanResultConsumer> metaTable = ASYNC_CONN.getTable(META_TABLE_NAME);
246 List<HRegionLocation> regionLocations = ClientMetaTableAccessor
247 .getTableHRegionLocations(metaTable, tableName).get();
248 assertEquals(1, regionLocations.size());
250 AsyncTable<?> table = ASYNC_CONN.getTable(tableName);
251 List<Put> puts = new ArrayList<>();
252 for (int i = 0; i < rowCount; i++) {
253 Put put = new Put(Bytes.toBytes(i));
254 put.addColumn(FAMILY, null, Bytes.toBytes("value" + i));
255 puts.add(put);
257 table.putAll(puts).join();
259 if (isSplitRegion) {
260 if (splitPoint == null) {
261 admin.splitRegion(regionLocations.get(0).getRegion().getRegionName()).get();
262 } else {
263 admin.splitRegion(regionLocations.get(0).getRegion().getRegionName(), splitPoint).get();
265 } else {
266 if (splitPoint == null) {
267 admin.split(tableName).get();
268 } else {
269 admin.split(tableName, splitPoint).get();
273 int count = 0;
274 for (int i = 0; i < 45; i++) {
275 try {
276 regionLocations = ClientMetaTableAccessor
277 .getTableHRegionLocations(metaTable, tableName).get();
278 count = regionLocations.size();
279 if (count >= 2) {
280 break;
282 Thread.sleep(1000L);
283 } catch (Exception e) {
284 LOG.error(e.toString(), e);
287 assertEquals(2, count);