001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertFalse; 022import static org.junit.Assert.assertNotNull; 023import static org.junit.Assert.assertTrue; 024import static org.junit.Assert.fail; 025 026import java.io.IOException; 027import java.util.ArrayList; 028import java.util.List; 029import java.util.concurrent.ExecutionException; 030import java.util.concurrent.TimeUnit; 031import java.util.concurrent.atomic.AtomicInteger; 032import org.apache.hadoop.hbase.HBaseClassTestRule; 033import org.apache.hadoop.hbase.HConstants; 034import org.apache.hadoop.hbase.HRegionLocation; 035import org.apache.hadoop.hbase.MetaTableAccessor; 036import org.apache.hadoop.hbase.ServerName; 037import org.apache.hadoop.hbase.TableName; 038import org.apache.hadoop.hbase.TableNotFoundException; 039import org.apache.hadoop.hbase.exceptions.MergeRegionException; 040import org.apache.hadoop.hbase.master.HMaster; 041import org.apache.hadoop.hbase.master.janitor.CatalogJanitor; 042import org.apache.hadoop.hbase.regionserver.DisabledRegionSplitPolicy; 043import org.apache.hadoop.hbase.regionserver.HRegion; 044import org.apache.hadoop.hbase.regionserver.HStore; 045import org.apache.hadoop.hbase.regionserver.HStoreFile; 046import org.apache.hadoop.hbase.testclassification.ClientTests; 047import org.apache.hadoop.hbase.testclassification.LargeTests; 048import org.apache.hadoop.hbase.util.Bytes; 049import org.apache.hadoop.hbase.util.CommonFSUtils; 050import org.apache.hadoop.hbase.util.Pair; 051import org.apache.hadoop.hbase.util.Threads; 052import org.junit.ClassRule; 053import org.junit.Test; 054import org.junit.experimental.categories.Category; 055import org.slf4j.Logger; 056import org.slf4j.LoggerFactory; 057 058import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; 059import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MergeTableRegionsRequest; 060 061/** 062 * Class to test HBaseAdmin. Spins up the minicluster once at test start and then takes it down 063 * afterward. Add any testing of HBaseAdmin functionality here. 064 */ 065@Category({ LargeTests.class, ClientTests.class }) 066public class TestAdmin1 extends TestAdminBase { 067 068 @ClassRule 069 public static final HBaseClassTestRule CLASS_RULE = HBaseClassTestRule.forClass(TestAdmin1.class); 070 071 private static final Logger LOG = LoggerFactory.getLogger(TestAdmin1.class); 072 073 @Test 074 public void testSplitFlushCompactUnknownTable() throws InterruptedException { 075 final TableName unknowntable = TableName.valueOf(name.getMethodName()); 076 Exception exception = null; 077 try { 078 ADMIN.compact(unknowntable); 079 } catch (IOException e) { 080 exception = e; 081 } 082 assertTrue(exception instanceof TableNotFoundException); 083 084 exception = null; 085 try { 086 ADMIN.flush(unknowntable); 087 } catch (IOException e) { 088 exception = e; 089 } 090 assertTrue(exception instanceof TableNotFoundException); 091 092 exception = null; 093 try { 094 ADMIN.split(unknowntable); 095 } catch (IOException e) { 096 exception = e; 097 } 098 assertTrue(exception instanceof TableNotFoundException); 099 } 100 101 @Test 102 public void testCompactionTimestamps() throws Exception { 103 TableName tableName = TableName.valueOf(name.getMethodName()); 104 TableDescriptor htd = TableDescriptorBuilder.newBuilder(tableName) 105 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("fam1")).build(); 106 ADMIN.createTable(htd); 107 Table table = TEST_UTIL.getConnection().getTable(htd.getTableName()); 108 long ts = ADMIN.getLastMajorCompactionTimestamp(tableName); 109 assertEquals(0, ts); 110 Put p = new Put(Bytes.toBytes("row1")); 111 p.addColumn(Bytes.toBytes("fam1"), Bytes.toBytes("fam1"), Bytes.toBytes("fam1")); 112 table.put(p); 113 ts = ADMIN.getLastMajorCompactionTimestamp(tableName); 114 // no files written -> no data 115 assertEquals(0, ts); 116 117 ADMIN.flush(tableName); 118 ts = ADMIN.getLastMajorCompactionTimestamp(tableName); 119 // still 0, we flushed a file, but no major compaction happened 120 assertEquals(0, ts); 121 122 byte[] regionName; 123 try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(tableName)) { 124 regionName = l.getAllRegionLocations().get(0).getRegion().getRegionName(); 125 } 126 long ts1 = ADMIN.getLastMajorCompactionTimestampForRegion(regionName); 127 assertEquals(ts, ts1); 128 p = new Put(Bytes.toBytes("row2")); 129 p.addColumn(Bytes.toBytes("fam1"), Bytes.toBytes("fam1"), Bytes.toBytes("fam1")); 130 table.put(p); 131 ADMIN.flush(tableName); 132 ts = ADMIN.getLastMajorCompactionTimestamp(tableName); 133 // make sure the region API returns the same value, as the old file is still around 134 assertEquals(ts1, ts); 135 136 TEST_UTIL.compact(tableName, true); 137 table.put(p); 138 // forces a wait for the compaction 139 ADMIN.flush(tableName); 140 ts = ADMIN.getLastMajorCompactionTimestamp(tableName); 141 // after a compaction our earliest timestamp will have progressed forward 142 assertTrue(ts > ts1); 143 144 // region api still the same 145 ts1 = ADMIN.getLastMajorCompactionTimestampForRegion(regionName); 146 assertEquals(ts, ts1); 147 table.put(p); 148 ADMIN.flush(tableName); 149 ts = ADMIN.getLastMajorCompactionTimestamp(tableName); 150 assertEquals(ts, ts1); 151 table.close(); 152 } 153 154 @Test(expected = IllegalArgumentException.class) 155 public void testColumnValidName() { 156 ColumnFamilyDescriptorBuilder.of("\\test\\abc"); 157 } 158 159 @Test 160 public void testTableExist() throws IOException { 161 final TableName table = TableName.valueOf(name.getMethodName()); 162 boolean exist; 163 exist = ADMIN.tableExists(table); 164 assertEquals(false, exist); 165 TEST_UTIL.createTable(table, HConstants.CATALOG_FAMILY); 166 exist = ADMIN.tableExists(table); 167 assertEquals(true, exist); 168 } 169 170 /** 171 * Tests forcing split from client and having scanners successfully ride over split. 172 */ 173 @Test 174 public void testForceSplit() throws Exception { 175 byte[][] familyNames = new byte[][] { Bytes.toBytes("cf") }; 176 int[] rowCounts = new int[] { 6000 }; 177 int numVersions = ColumnFamilyDescriptorBuilder.DEFAULT_MAX_VERSIONS; 178 int blockSize = 256; 179 splitTest(null, familyNames, rowCounts, numVersions, blockSize, true); 180 181 byte[] splitKey = Bytes.toBytes(3500); 182 splitTest(splitKey, familyNames, rowCounts, numVersions, blockSize, true); 183 // test regionSplitSync 184 splitTest(splitKey, familyNames, rowCounts, numVersions, blockSize, false); 185 } 186 187 /** 188 * Multi-family scenario. Tests forcing split from client and having scanners successfully ride 189 * over split. 190 */ 191 @Test 192 public void testForceSplitMultiFamily() throws Exception { 193 int numVersions = ColumnFamilyDescriptorBuilder.DEFAULT_MAX_VERSIONS; 194 195 // use small HFile block size so that we can have lots of blocks in HFile 196 // Otherwise, if there is only one block, 197 // HFileBlockIndex.midKey()'s value == startKey 198 int blockSize = 256; 199 byte[][] familyNames = new byte[][] { Bytes.toBytes("cf1"), Bytes.toBytes("cf2") }; 200 201 // one of the column families isn't splittable 202 int[] rowCounts = new int[] { 6000, 1 }; 203 splitTest(null, familyNames, rowCounts, numVersions, blockSize, true); 204 205 rowCounts = new int[] { 1, 6000 }; 206 splitTest(null, familyNames, rowCounts, numVersions, blockSize, true); 207 208 // one column family has much smaller data than the other 209 // the split key should be based on the largest column family 210 rowCounts = new int[] { 6000, 300 }; 211 splitTest(null, familyNames, rowCounts, numVersions, blockSize, true); 212 213 rowCounts = new int[] { 300, 6000 }; 214 splitTest(null, familyNames, rowCounts, numVersions, blockSize, true); 215 } 216 217 private int count(ResultScanner scanner) throws IOException { 218 int rows = 0; 219 while (scanner.next() != null) { 220 rows++; 221 } 222 return rows; 223 } 224 225 private void splitTest(byte[] splitPoint, byte[][] familyNames, int[] rowCounts, int numVersions, 226 int blockSize, boolean async) throws Exception { 227 TableName tableName = TableName.valueOf("testForceSplit"); 228 StringBuilder sb = new StringBuilder(); 229 // Add tail to String so can see better in logs where a test is running. 230 for (int i = 0; i < rowCounts.length; i++) { 231 sb.append("_").append(Integer.toString(rowCounts[i])); 232 } 233 assertFalse(ADMIN.tableExists(tableName)); 234 try (final Table table = TEST_UTIL.createTable(tableName, familyNames, numVersions, blockSize); 235 final RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(tableName)) { 236 237 int rowCount = 0; 238 byte[] q = new byte[0]; 239 240 // insert rows into column families. The number of rows that have values 241 // in a specific column family is decided by rowCounts[familyIndex] 242 for (int index = 0; index < familyNames.length; index++) { 243 ArrayList<Put> puts = new ArrayList<>(rowCounts[index]); 244 for (int i = 0; i < rowCounts[index]; i++) { 245 byte[] k = Bytes.toBytes(i); 246 Put put = new Put(k); 247 put.addColumn(familyNames[index], q, k); 248 puts.add(put); 249 } 250 table.put(puts); 251 252 if (rowCount < rowCounts[index]) { 253 rowCount = rowCounts[index]; 254 } 255 } 256 257 // get the initial layout (should just be one region) 258 List<HRegionLocation> m = locator.getAllRegionLocations(); 259 LOG.info("Initial regions (" + m.size() + "): " + m); 260 assertTrue(m.size() == 1); 261 262 // Verify row count 263 Scan scan = new Scan(); 264 int rows; 265 try (ResultScanner scanner = table.getScanner(scan)) { 266 rows = count(scanner); 267 } 268 assertEquals(rowCount, rows); 269 270 // Have an outstanding scan going on to make sure we can scan over splits. 271 scan = new Scan(); 272 try (ResultScanner scanner = table.getScanner(scan)) { 273 // Scan first row so we are into first region before split happens. 274 scanner.next(); 275 276 // Split the table 277 if (async) { 278 ADMIN.split(tableName, splitPoint); 279 final AtomicInteger count = new AtomicInteger(0); 280 Thread t = new Thread("CheckForSplit") { 281 @Override 282 public void run() { 283 for (int i = 0; i < 45; i++) { 284 try { 285 sleep(1000); 286 } catch (InterruptedException e) { 287 continue; 288 } 289 // check again 290 List<HRegionLocation> regions = null; 291 try { 292 regions = locator.getAllRegionLocations(); 293 } catch (IOException e) { 294 LOG.warn("get location failed", e); 295 } 296 if (regions == null) { 297 continue; 298 } 299 count.set(regions.size()); 300 if (count.get() >= 2) { 301 LOG.info("Found: " + regions); 302 break; 303 } 304 LOG.debug("Cycle waiting on split"); 305 } 306 LOG.debug("CheckForSplit thread exited, current region count: " + count.get()); 307 } 308 }; 309 t.setPriority(Thread.NORM_PRIORITY - 2); 310 t.start(); 311 t.join(); 312 } else { 313 // Sync split region, no need to create a thread to check 314 ADMIN.splitRegionAsync(m.get(0).getRegion().getRegionName(), splitPoint).get(); 315 } 316 // Verify row count 317 rows = 1 + count(scanner); // We counted one row above. 318 } 319 assertEquals(rowCount, rows); 320 321 List<HRegionLocation> regions = null; 322 try { 323 regions = locator.getAllRegionLocations(); 324 } catch (IOException e) { 325 e.printStackTrace(); 326 } 327 assertEquals(2, regions.size()); 328 if (splitPoint != null) { 329 // make sure the split point matches our explicit configuration 330 assertEquals(Bytes.toString(splitPoint), 331 Bytes.toString(regions.get(0).getRegion().getEndKey())); 332 assertEquals(Bytes.toString(splitPoint), 333 Bytes.toString(regions.get(1).getRegion().getStartKey())); 334 LOG.debug("Properly split on " + Bytes.toString(splitPoint)); 335 } else { 336 if (familyNames.length > 1) { 337 int splitKey = Bytes.toInt(regions.get(0).getRegion().getEndKey()); 338 // check if splitKey is based on the largest column family 339 // in terms of it store size 340 int deltaForLargestFamily = Math.abs(rowCount / 2 - splitKey); 341 LOG.debug("SplitKey=" + splitKey + "&deltaForLargestFamily=" + deltaForLargestFamily + 342 ", r=" + regions.get(0).getRegion()); 343 for (int index = 0; index < familyNames.length; index++) { 344 int delta = Math.abs(rowCounts[index] / 2 - splitKey); 345 if (delta < deltaForLargestFamily) { 346 assertTrue("Delta " + delta + " for family " + index + " should be at least " + 347 "deltaForLargestFamily " + deltaForLargestFamily, false); 348 } 349 } 350 } 351 } 352 TEST_UTIL.deleteTable(tableName); 353 } 354 } 355 356 @Test 357 public void testSplitAndMergeWithReplicaTable() throws Exception { 358 // The test tries to directly split replica regions and directly merge replica regions. These 359 // are not allowed. The test validates that. Then the test does a valid split/merge of allowed 360 // regions. 361 // Set up a table with 3 regions and replication set to 3 362 TableName tableName = TableName.valueOf(name.getMethodName()); 363 byte[] cf = Bytes.toBytes("f"); 364 TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName).setRegionReplication(3) 365 .setColumnFamily(ColumnFamilyDescriptorBuilder.of(cf)).build(); 366 byte[][] splitRows = new byte[2][]; 367 splitRows[0] = new byte[] { (byte) '4' }; 368 splitRows[1] = new byte[] { (byte) '7' }; 369 TEST_UTIL.getAdmin().createTable(desc, splitRows); 370 List<HRegion> oldRegions; 371 do { 372 oldRegions = TEST_UTIL.getHBaseCluster().getRegions(tableName); 373 Thread.sleep(10); 374 } while (oldRegions.size() != 9); // 3 regions * 3 replicas 375 // write some data to the table 376 Table ht = TEST_UTIL.getConnection().getTable(tableName); 377 List<Put> puts = new ArrayList<>(); 378 byte[] qualifier = Bytes.toBytes("c"); 379 Put put = new Put(new byte[] { (byte) '1' }); 380 put.addColumn(cf, qualifier, Bytes.toBytes("100")); 381 puts.add(put); 382 put = new Put(new byte[] { (byte) '6' }); 383 put.addColumn(cf, qualifier, Bytes.toBytes("100")); 384 puts.add(put); 385 put = new Put(new byte[] { (byte) '8' }); 386 put.addColumn(cf, qualifier, Bytes.toBytes("100")); 387 puts.add(put); 388 ht.put(puts); 389 ht.close(); 390 List<Pair<RegionInfo, ServerName>> regions = 391 MetaTableAccessor.getTableRegionsAndLocations(TEST_UTIL.getConnection(), tableName); 392 boolean gotException = false; 393 // the element at index 1 would be a replica (since the metareader gives us ordered 394 // regions). Try splitting that region via the split API . Should fail 395 try { 396 TEST_UTIL.getAdmin().splitRegionAsync(regions.get(1).getFirst().getRegionName()).get(); 397 } catch (IllegalArgumentException ex) { 398 gotException = true; 399 } 400 assertTrue(gotException); 401 gotException = false; 402 // the element at index 1 would be a replica (since the metareader gives us ordered 403 // regions). Try splitting that region via a different split API (the difference is 404 // this API goes direct to the regionserver skipping any checks in the admin). Should fail 405 try { 406 TEST_UTIL.getHBaseAdmin().splitRegionAsync(regions.get(1).getFirst(), 407 new byte[] { (byte) '1' }); 408 } catch (IOException ex) { 409 gotException = true; 410 } 411 assertTrue(gotException); 412 413 gotException = false; 414 // testing Sync split operation 415 try { 416 TEST_UTIL.getAdmin() 417 .splitRegionAsync(regions.get(1).getFirst().getRegionName(), new byte[] { (byte) '1' }) 418 .get(); 419 } catch (IllegalArgumentException ex) { 420 gotException = true; 421 } 422 assertTrue(gotException); 423 424 gotException = false; 425 // Try merging a replica with another. Should fail. 426 try { 427 TEST_UTIL.getAdmin().mergeRegionsAsync(regions.get(1).getFirst().getEncodedNameAsBytes(), 428 regions.get(2).getFirst().getEncodedNameAsBytes(), true).get(); 429 } catch (IllegalArgumentException m) { 430 gotException = true; 431 } 432 assertTrue(gotException); 433 // Try going to the master directly (that will skip the check in admin) 434 try { 435 byte[][] nameofRegionsToMerge = new byte[2][]; 436 nameofRegionsToMerge[0] = regions.get(1).getFirst().getEncodedNameAsBytes(); 437 nameofRegionsToMerge[1] = regions.get(2).getFirst().getEncodedNameAsBytes(); 438 MergeTableRegionsRequest request = RequestConverter.buildMergeTableRegionsRequest( 439 nameofRegionsToMerge, true, HConstants.NO_NONCE, HConstants.NO_NONCE); 440 ((ClusterConnection) TEST_UTIL.getAdmin().getConnection()).getMaster().mergeTableRegions(null, 441 request); 442 } catch (org.apache.hbase.thirdparty.com.google.protobuf.ServiceException m) { 443 Throwable t = m.getCause(); 444 do { 445 if (t instanceof MergeRegionException) { 446 gotException = true; 447 break; 448 } 449 t = t.getCause(); 450 } while (t != null); 451 } 452 assertTrue(gotException); 453 } 454 455 @Test(expected = IllegalArgumentException.class) 456 public void testInvalidColumnDescriptor() throws IOException { 457 ColumnFamilyDescriptorBuilder.of("/cfamily/name"); 458 } 459 460 /** 461 * Test DFS replication for column families, where one CF has default replication(3) and the other 462 * is set to 1. 463 */ 464 @Test 465 public void testHFileReplication() throws Exception { 466 final TableName tableName = TableName.valueOf(this.name.getMethodName()); 467 String fn1 = "rep1"; 468 String fn = "defaultRep"; 469 TableDescriptor htd = TableDescriptorBuilder.newBuilder(tableName) 470 .setColumnFamily(ColumnFamilyDescriptorBuilder.of(fn)) 471 .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(fn1)) 472 .setDFSReplication((short) 1).build()) 473 .build(); 474 Table table = TEST_UTIL.createTable(htd, null); 475 TEST_UTIL.waitTableAvailable(tableName); 476 Put p = new Put(Bytes.toBytes("defaultRep_rk")); 477 byte[] q1 = Bytes.toBytes("q1"); 478 byte[] v1 = Bytes.toBytes("v1"); 479 p.addColumn(Bytes.toBytes(fn), q1, v1); 480 List<Put> puts = new ArrayList<>(2); 481 puts.add(p); 482 p = new Put(Bytes.toBytes("rep1_rk")); 483 p.addColumn(Bytes.toBytes(fn1), q1, v1); 484 puts.add(p); 485 try { 486 table.put(puts); 487 ADMIN.flush(tableName); 488 489 List<HRegion> regions = TEST_UTIL.getMiniHBaseCluster().getRegions(tableName); 490 for (HRegion r : regions) { 491 HStore store = r.getStore(Bytes.toBytes(fn)); 492 for (HStoreFile sf : store.getStorefiles()) { 493 assertTrue(sf.toString().contains(fn)); 494 assertTrue("Column family " + fn + " should have 3 copies", 495 CommonFSUtils.getDefaultReplication(TEST_UTIL.getTestFileSystem(), 496 sf.getPath()) == (sf.getFileInfo().getFileStatus().getReplication())); 497 } 498 499 store = r.getStore(Bytes.toBytes(fn1)); 500 for (HStoreFile sf : store.getStorefiles()) { 501 assertTrue(sf.toString().contains(fn1)); 502 assertTrue("Column family " + fn1 + " should have only 1 copy", 503 1 == sf.getFileInfo().getFileStatus().getReplication()); 504 } 505 } 506 } finally { 507 if (ADMIN.isTableEnabled(tableName)) { 508 ADMIN.disableTable(tableName); 509 ADMIN.deleteTable(tableName); 510 } 511 } 512 } 513 514 @Test 515 public void testMergeRegions() throws Exception { 516 final TableName tableName = TableName.valueOf(name.getMethodName()); 517 TableDescriptor td = TableDescriptorBuilder.newBuilder(tableName) 518 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("d")).build(); 519 byte[][] splitRows = new byte[2][]; 520 splitRows[0] = new byte[] { (byte) '3' }; 521 splitRows[1] = new byte[] { (byte) '6' }; 522 try { 523 TEST_UTIL.createTable(td, splitRows); 524 TEST_UTIL.waitTableAvailable(tableName); 525 526 List<RegionInfo> tableRegions; 527 RegionInfo regionA; 528 RegionInfo regionB; 529 RegionInfo regionC; 530 RegionInfo mergedChildRegion = null; 531 532 // merge with full name 533 tableRegions = ADMIN.getRegions(tableName); 534 assertEquals(3, tableRegions.size()); 535 regionA = tableRegions.get(0); 536 regionB = tableRegions.get(1); 537 regionC = tableRegions.get(2); 538 // TODO convert this to version that is synchronous (See HBASE-16668) 539 ADMIN.mergeRegionsAsync(regionA.getRegionName(), regionB.getRegionName(), 540 false).get(60, TimeUnit.SECONDS); 541 542 tableRegions = ADMIN.getRegions(tableName); 543 544 assertEquals(2, tableRegions.size()); 545 for (RegionInfo ri : tableRegions) { 546 if (regionC.compareTo(ri) != 0) { 547 mergedChildRegion = ri; 548 break; 549 } 550 } 551 552 assertNotNull(mergedChildRegion); 553 // Need to wait GC for merged child region is done. 554 HMaster services = TEST_UTIL.getHBaseCluster().getMaster(); 555 CatalogJanitor cj = services.getCatalogJanitor(); 556 assertTrue(cj.scan() > 0); 557 // Wait until all procedures settled down 558 while (!services.getMasterProcedureExecutor().getActiveProcIds().isEmpty()) { 559 Thread.sleep(200); 560 } 561 562 // TODO convert this to version that is synchronous (See HBASE-16668) 563 ADMIN.mergeRegionsAsync(regionC.getEncodedNameAsBytes(), 564 mergedChildRegion.getEncodedNameAsBytes(), false) 565 .get(60, TimeUnit.SECONDS); 566 567 assertEquals(1, ADMIN.getRegions(tableName).size()); 568 } finally { 569 ADMIN.disableTable(tableName); 570 ADMIN.deleteTable(tableName); 571 } 572 } 573 574 @Test 575 public void testMergeRegionsInvalidRegionCount() 576 throws IOException, InterruptedException, ExecutionException { 577 TableName tableName = TableName.valueOf(name.getMethodName()); 578 TableDescriptor td = TableDescriptorBuilder.newBuilder(tableName) 579 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("d")).build(); 580 byte[][] splitRows = new byte[2][]; 581 splitRows[0] = new byte[] { (byte) '3' }; 582 splitRows[1] = new byte[] { (byte) '6' }; 583 try { 584 TEST_UTIL.createTable(td, splitRows); 585 TEST_UTIL.waitTableAvailable(tableName); 586 587 List<RegionInfo> tableRegions = ADMIN.getRegions(tableName); 588 // 0 589 try { 590 ADMIN.mergeRegionsAsync(new byte[0][0], false).get(); 591 fail(); 592 } catch (IllegalArgumentException e) { 593 // expected 594 } 595 // 1 596 try { 597 ADMIN.mergeRegionsAsync(new byte[][] { tableRegions.get(0).getEncodedNameAsBytes() }, false) 598 .get(); 599 fail(); 600 } catch (IllegalArgumentException e) { 601 // expected 602 } 603 } finally { 604 ADMIN.disableTable(tableName); 605 ADMIN.deleteTable(tableName); 606 } 607 } 608 609 @Test 610 public void testSplitShouldNotHappenIfSplitIsDisabledForTable() throws Exception { 611 final TableName tableName = TableName.valueOf(name.getMethodName()); 612 TableDescriptor htd = TableDescriptorBuilder.newBuilder(tableName) 613 .setRegionSplitPolicyClassName(DisabledRegionSplitPolicy.class.getName()) 614 .setColumnFamily(ColumnFamilyDescriptorBuilder.of("f")).build(); 615 Table table = TEST_UTIL.createTable(htd, null); 616 for (int i = 0; i < 10; i++) { 617 Put p = new Put(Bytes.toBytes("row" + i)); 618 byte[] q1 = Bytes.toBytes("q1"); 619 byte[] v1 = Bytes.toBytes("v1"); 620 p.addColumn(Bytes.toBytes("f"), q1, v1); 621 table.put(p); 622 } 623 ADMIN.flush(tableName); 624 try { 625 ADMIN.split(tableName, Bytes.toBytes("row5")); 626 Threads.sleep(10000); 627 } catch (Exception e) { 628 // Nothing to do. 629 } 630 // Split should not happen. 631 List<RegionInfo> allRegions = 632 MetaTableAccessor.getTableRegions(ADMIN.getConnection(), tableName, true); 633 assertEquals(1, allRegions.size()); 634 } 635}