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.assertTrue; 023import static org.junit.Assert.fail; 024 025import java.io.IOException; 026import java.util.ArrayList; 027import java.util.EnumSet; 028import java.util.HashMap; 029import java.util.List; 030import java.util.Random; 031import java.util.concurrent.atomic.AtomicInteger; 032import java.util.stream.Collectors; 033import org.apache.hadoop.conf.Configuration; 034import org.apache.hadoop.hbase.ClusterMetrics.Option; 035import org.apache.hadoop.hbase.HBaseClassTestRule; 036import org.apache.hadoop.hbase.HBaseTestingUtility; 037import org.apache.hadoop.hbase.HColumnDescriptor; 038import org.apache.hadoop.hbase.HConstants; 039import org.apache.hadoop.hbase.HRegionLocation; 040import org.apache.hadoop.hbase.HTableDescriptor; 041import org.apache.hadoop.hbase.MiniHBaseCluster; 042import org.apache.hadoop.hbase.ServerName; 043import org.apache.hadoop.hbase.TableExistsException; 044import org.apache.hadoop.hbase.TableName; 045import org.apache.hadoop.hbase.TableNotDisabledException; 046import org.apache.hadoop.hbase.TableNotEnabledException; 047import org.apache.hadoop.hbase.TableNotFoundException; 048import org.apache.hadoop.hbase.UnknownRegionException; 049import org.apache.hadoop.hbase.ZooKeeperConnectionException; 050import org.apache.hadoop.hbase.constraint.ConstraintException; 051import org.apache.hadoop.hbase.ipc.RpcScheduler; 052import org.apache.hadoop.hbase.master.HMaster; 053import org.apache.hadoop.hbase.master.assignment.AssignmentManager; 054import org.apache.hadoop.hbase.regionserver.HRegion; 055import org.apache.hadoop.hbase.regionserver.HRegionServer; 056import org.apache.hadoop.hbase.testclassification.ClientTests; 057import org.apache.hadoop.hbase.testclassification.LargeTests; 058import org.apache.hadoop.hbase.util.Bytes; 059import org.apache.hadoop.hbase.util.Pair; 060import org.apache.hadoop.hbase.wal.AbstractFSWALProvider; 061import org.junit.After; 062import org.junit.AfterClass; 063import org.junit.Before; 064import org.junit.BeforeClass; 065import org.junit.ClassRule; 066import org.junit.Rule; 067import org.junit.Test; 068import org.junit.experimental.categories.Category; 069import org.junit.rules.TestName; 070import org.slf4j.Logger; 071import org.slf4j.LoggerFactory; 072 073import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 074 075/** 076 * Class to test HBaseAdmin. 077 * Spins up the minicluster once at test start and then takes it down afterward. 078 * Add any testing of HBaseAdmin functionality here. 079 */ 080@Category({LargeTests.class, ClientTests.class}) 081public class TestAdmin2 { 082 083 @ClassRule 084 public static final HBaseClassTestRule CLASS_RULE = 085 HBaseClassTestRule.forClass(TestAdmin2.class); 086 087 private static final Logger LOG = LoggerFactory.getLogger(TestAdmin2.class); 088 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 089 private Admin admin; 090 091 @Rule 092 public TestName name = new TestName(); 093 094 @BeforeClass 095 public static void setUpBeforeClass() throws Exception { 096 TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100); 097 TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250); 098 TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 6); 099 TEST_UTIL.getConfiguration().setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 30); 100 TEST_UTIL.getConfiguration().setInt(HConstants.REGION_SERVER_HANDLER_COUNT, 30); 101 TEST_UTIL.getConfiguration().setBoolean("hbase.master.enabletable.roundrobin", true); 102 TEST_UTIL.startMiniCluster(3); 103 } 104 105 @AfterClass 106 public static void tearDownAfterClass() throws Exception { 107 TEST_UTIL.shutdownMiniCluster(); 108 } 109 110 @Before 111 public void setUp() throws Exception { 112 this.admin = TEST_UTIL.getHBaseAdmin(); 113 } 114 115 @After 116 public void tearDown() throws Exception { 117 for (HTableDescriptor htd : this.admin.listTables()) { 118 TEST_UTIL.deleteTable(htd.getTableName()); 119 } 120 } 121 122 @Test 123 public void testCreateBadTables() throws IOException { 124 String msg = null; 125 try { 126 this.admin.createTable(new HTableDescriptor(TableName.META_TABLE_NAME)); 127 } catch(TableExistsException e) { 128 msg = e.toString(); 129 } 130 assertTrue("Unexcepted exception message " + msg, msg != null && 131 msg.startsWith(TableExistsException.class.getName()) && 132 msg.contains(TableName.META_TABLE_NAME.getNameAsString())); 133 134 // Now try and do concurrent creation with a bunch of threads. 135 final HTableDescriptor threadDesc = new HTableDescriptor(TableName.valueOf(name.getMethodName())); 136 threadDesc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 137 int count = 10; 138 Thread [] threads = new Thread [count]; 139 final AtomicInteger successes = new AtomicInteger(0); 140 final AtomicInteger failures = new AtomicInteger(0); 141 final Admin localAdmin = this.admin; 142 for (int i = 0; i < count; i++) { 143 threads[i] = new Thread(Integer.toString(i)) { 144 @Override 145 public void run() { 146 try { 147 localAdmin.createTable(threadDesc); 148 successes.incrementAndGet(); 149 } catch (TableExistsException e) { 150 failures.incrementAndGet(); 151 } catch (IOException e) { 152 throw new RuntimeException("Failed threaded create" + getName(), e); 153 } 154 } 155 }; 156 } 157 for (int i = 0; i < count; i++) { 158 threads[i].start(); 159 } 160 for (int i = 0; i < count; i++) { 161 while(threads[i].isAlive()) { 162 try { 163 Thread.sleep(100); 164 } catch (InterruptedException e) { 165 // continue 166 } 167 } 168 } 169 // All threads are now dead. Count up how many tables were created and 170 // how many failed w/ appropriate exception. 171 assertEquals(1, successes.get()); 172 assertEquals(count - 1, failures.get()); 173 } 174 175 /** 176 * Test for hadoop-1581 'HBASE: Unopenable tablename bug'. 177 * @throws Exception 178 */ 179 @Test 180 public void testTableNameClash() throws Exception { 181 final String name = this.name.getMethodName(); 182 HTableDescriptor htd1 = new HTableDescriptor(TableName.valueOf(name + "SOMEUPPERCASE")); 183 HTableDescriptor htd2 = new HTableDescriptor(TableName.valueOf(name)); 184 htd1.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 185 htd2.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 186 admin.createTable(htd1); 187 admin.createTable(htd2); 188 // Before fix, below would fail throwing a NoServerForRegionException. 189 TEST_UTIL.getConnection().getTable(htd2.getTableName()).close(); 190 } 191 192 /*** 193 * HMaster.createTable used to be kind of synchronous call 194 * Thus creating of table with lots of regions can cause RPC timeout 195 * After the fix to make createTable truly async, RPC timeout shouldn't be an 196 * issue anymore 197 * @throws Exception 198 */ 199 @Test 200 public void testCreateTableRPCTimeOut() throws Exception { 201 final String name = this.name.getMethodName(); 202 int oldTimeout = TEST_UTIL.getConfiguration(). 203 getInt(HConstants.HBASE_RPC_TIMEOUT_KEY, HConstants.DEFAULT_HBASE_RPC_TIMEOUT); 204 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1500); 205 try { 206 int expectedRegions = 100; 207 // Use 80 bit numbers to make sure we aren't limited 208 byte [] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 209 byte [] endKey = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; 210 Admin hbaseadmin = TEST_UTIL.getHBaseAdmin(); 211 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(name)); 212 htd.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 213 hbaseadmin.createTable(htd, startKey, endKey, expectedRegions); 214 } finally { 215 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, oldTimeout); 216 } 217 } 218 219 /** 220 * Test read only tables 221 * @throws Exception 222 */ 223 @Test 224 public void testReadOnlyTable() throws Exception { 225 final TableName name = TableName.valueOf(this.name.getMethodName()); 226 Table table = TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY); 227 byte[] value = Bytes.toBytes("somedata"); 228 // This used to use an empty row... That must have been a bug 229 Put put = new Put(value); 230 put.addColumn(HConstants.CATALOG_FAMILY, HConstants.CATALOG_FAMILY, value); 231 table.put(put); 232 table.close(); 233 } 234 235 /** 236 * Test that user table names can contain '-' and '.' so long as they do not 237 * start with same. HBASE-771 238 * @throws IOException 239 */ 240 @Test 241 public void testTableNames() throws IOException { 242 byte[][] illegalNames = new byte[][] { 243 Bytes.toBytes("-bad"), 244 Bytes.toBytes(".bad") 245 }; 246 for (byte[] illegalName : illegalNames) { 247 try { 248 new HTableDescriptor(TableName.valueOf(illegalName)); 249 throw new IOException("Did not detect '" + 250 Bytes.toString(illegalName) + "' as an illegal user table name"); 251 } catch (IllegalArgumentException e) { 252 // expected 253 } 254 } 255 byte[] legalName = Bytes.toBytes("g-oo.d"); 256 try { 257 new HTableDescriptor(TableName.valueOf(legalName)); 258 } catch (IllegalArgumentException e) { 259 throw new IOException("Legal user table name: '" + 260 Bytes.toString(legalName) + "' caused IllegalArgumentException: " + 261 e.getMessage()); 262 } 263 } 264 265 /** 266 * For HADOOP-2579 267 * @throws IOException 268 */ 269 @Test (expected=TableExistsException.class) 270 public void testTableExistsExceptionWithATable() throws IOException { 271 final TableName name = TableName.valueOf(this.name.getMethodName()); 272 TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY).close(); 273 TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY); 274 } 275 276 /** 277 * Can't disable a table if the table isn't in enabled state 278 * @throws IOException 279 */ 280 @Test (expected=TableNotEnabledException.class) 281 public void testTableNotEnabledExceptionWithATable() throws IOException { 282 final TableName name = TableName.valueOf(this.name.getMethodName()); 283 TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY).close(); 284 this.admin.disableTable(name); 285 this.admin.disableTable(name); 286 } 287 288 /** 289 * Can't enable a table if the table isn't in disabled state 290 * @throws IOException 291 */ 292 @Test (expected=TableNotDisabledException.class) 293 public void testTableNotDisabledExceptionWithATable() throws IOException { 294 final TableName name = TableName.valueOf(this.name.getMethodName()); 295 Table t = TEST_UTIL.createTable(name, HConstants.CATALOG_FAMILY); 296 try { 297 this.admin.enableTable(name); 298 }finally { 299 t.close(); 300 } 301 } 302 303 /** 304 * For HADOOP-2579 305 * @throws IOException 306 */ 307 @Test (expected=TableNotFoundException.class) 308 public void testTableNotFoundExceptionWithoutAnyTables() throws IOException { 309 TableName tableName = TableName 310 .valueOf("testTableNotFoundExceptionWithoutAnyTables"); 311 Table ht = TEST_UTIL.getConnection().getTable(tableName); 312 ht.get(new Get(Bytes.toBytes("e"))); 313 } 314 315 @Test 316 public void testShouldUnassignTheRegion() throws Exception { 317 final TableName tableName = TableName.valueOf(name.getMethodName()); 318 createTableWithDefaultConf(tableName); 319 320 RegionInfo info = null; 321 HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(tableName); 322 List<RegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); 323 for (RegionInfo regionInfo : onlineRegions) { 324 if (!regionInfo.getTable().isSystemTable()) { 325 info = regionInfo; 326 admin.unassign(regionInfo.getRegionName(), true); 327 } 328 } 329 boolean isInList = ProtobufUtil.getOnlineRegions( 330 rs.getRSRpcServices()).contains(info); 331 long timeout = System.currentTimeMillis() + 10000; 332 while ((System.currentTimeMillis() < timeout) && (isInList)) { 333 Thread.sleep(100); 334 isInList = ProtobufUtil.getOnlineRegions( 335 rs.getRSRpcServices()).contains(info); 336 } 337 338 assertFalse("The region should not be present in online regions list.", 339 isInList); 340 } 341 342 @Test 343 public void testCloseRegionIfInvalidRegionNameIsPassed() throws Exception { 344 final String name = this.name.getMethodName(); 345 byte[] tableName = Bytes.toBytes(name); 346 createTableWithDefaultConf(tableName); 347 348 RegionInfo info = null; 349 HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TableName.valueOf(tableName)); 350 List<RegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); 351 for (RegionInfo regionInfo : onlineRegions) { 352 if (!regionInfo.isMetaRegion()) { 353 if (regionInfo.getRegionNameAsString().contains(name)) { 354 info = regionInfo; 355 try { 356 admin.unassign(Bytes.toBytes("sample"), true); 357 } catch (UnknownRegionException nsre) { 358 // expected, ignore it 359 } 360 } 361 } 362 } 363 onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); 364 assertTrue("The region should be present in online regions list.", 365 onlineRegions.contains(info)); 366 } 367 368 @Test 369 public void testCloseRegionThatFetchesTheHRIFromMeta() throws Exception { 370 final TableName tableName = TableName.valueOf(name.getMethodName()); 371 createTableWithDefaultConf(tableName); 372 373 RegionInfo info = null; 374 HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(tableName); 375 List<RegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); 376 for (RegionInfo regionInfo : onlineRegions) { 377 if (!regionInfo.isMetaRegion()) { 378 if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion2")) { 379 info = regionInfo; 380 admin.unassign(regionInfo.getRegionName(), true); 381 } 382 } 383 } 384 385 boolean isInList = ProtobufUtil.getOnlineRegions( 386 rs.getRSRpcServices()).contains(info); 387 long timeout = System.currentTimeMillis() + 10000; 388 while ((System.currentTimeMillis() < timeout) && (isInList)) { 389 Thread.sleep(100); 390 isInList = ProtobufUtil.getOnlineRegions( 391 rs.getRSRpcServices()).contains(info); 392 } 393 394 assertFalse("The region should not be present in online regions list.", 395 isInList); 396 } 397 398 private HBaseAdmin createTable(TableName tableName) throws IOException { 399 HBaseAdmin admin = TEST_UTIL.getHBaseAdmin(); 400 401 HTableDescriptor htd = new HTableDescriptor(tableName); 402 HColumnDescriptor hcd = new HColumnDescriptor("value"); 403 404 htd.addFamily(hcd); 405 admin.createTable(htd, null); 406 return admin; 407 } 408 409 private void createTableWithDefaultConf(byte[] TABLENAME) throws IOException { 410 createTableWithDefaultConf(TableName.valueOf(TABLENAME)); 411 } 412 413 private void createTableWithDefaultConf(TableName TABLENAME) throws IOException { 414 HTableDescriptor htd = new HTableDescriptor(TABLENAME); 415 HColumnDescriptor hcd = new HColumnDescriptor("value"); 416 htd.addFamily(hcd); 417 418 admin.createTable(htd, null); 419 } 420 421 /** 422 * For HBASE-2556 423 * @throws IOException 424 */ 425 @Test 426 public void testGetTableRegions() throws IOException { 427 final TableName tableName = TableName.valueOf(name.getMethodName()); 428 429 int expectedRegions = 10; 430 431 // Use 80 bit numbers to make sure we aren't limited 432 byte [] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 433 byte [] endKey = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; 434 435 436 HTableDescriptor desc = new HTableDescriptor(tableName); 437 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 438 admin.createTable(desc, startKey, endKey, expectedRegions); 439 440 List<RegionInfo> RegionInfos = admin.getRegions(tableName); 441 442 assertEquals("Tried to create " + expectedRegions + " regions " + 443 "but only found " + RegionInfos.size(), 444 expectedRegions, RegionInfos.size()); 445 } 446 447 @Test 448 public void testMoveToPreviouslyAssignedRS() throws IOException, InterruptedException { 449 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 450 HMaster master = cluster.getMaster(); 451 final TableName tableName = TableName.valueOf(name.getMethodName()); 452 Admin localAdmin = createTable(tableName); 453 List<RegionInfo> tableRegions = localAdmin.getRegions(tableName); 454 RegionInfo hri = tableRegions.get(0); 455 AssignmentManager am = master.getAssignmentManager(); 456 ServerName server = am.getRegionStates().getRegionServerOfRegion(hri); 457 localAdmin.move(hri.getEncodedNameAsBytes(), Bytes.toBytes(server.getServerName())); 458 assertEquals("Current region server and region server before move should be same.", server, 459 am.getRegionStates().getRegionServerOfRegion(hri)); 460 } 461 462 @Test 463 public void testWALRollWriting() throws Exception { 464 setUpforLogRolling(); 465 String className = this.getClass().getName(); 466 StringBuilder v = new StringBuilder(className); 467 while (v.length() < 1000) { 468 v.append(className); 469 } 470 byte[] value = Bytes.toBytes(v.toString()); 471 HRegionServer regionServer = startAndWriteData(TableName.valueOf(name.getMethodName()), value); 472 LOG.info("after writing there are " 473 + AbstractFSWALProvider.getNumRolledLogFiles(regionServer.getWAL(null)) + " log files"); 474 475 // flush all regions 476 for (HRegion r : regionServer.getOnlineRegionsLocalContext()) { 477 r.flush(true); 478 } 479 admin.rollWALWriter(regionServer.getServerName()); 480 int count = AbstractFSWALProvider.getNumRolledLogFiles(regionServer.getWAL(null)); 481 LOG.info("after flushing all regions and rolling logs there are " + 482 count + " log files"); 483 assertTrue(("actual count: " + count), count <= 2); 484 } 485 486 private void setUpforLogRolling() { 487 // Force a region split after every 768KB 488 TEST_UTIL.getConfiguration().setLong(HConstants.HREGION_MAX_FILESIZE, 489 768L * 1024L); 490 491 // We roll the log after every 32 writes 492 TEST_UTIL.getConfiguration().setInt("hbase.regionserver.maxlogentries", 32); 493 494 TEST_UTIL.getConfiguration().setInt( 495 "hbase.regionserver.logroll.errors.tolerated", 2); 496 TEST_UTIL.getConfiguration().setInt("hbase.rpc.timeout", 10 * 1000); 497 498 // For less frequently updated regions flush after every 2 flushes 499 TEST_UTIL.getConfiguration().setInt( 500 "hbase.hregion.memstore.optionalflushcount", 2); 501 502 // We flush the cache after every 8192 bytes 503 TEST_UTIL.getConfiguration().setInt(HConstants.HREGION_MEMSTORE_FLUSH_SIZE, 504 8192); 505 506 // Increase the amount of time between client retries 507 TEST_UTIL.getConfiguration().setLong("hbase.client.pause", 10 * 1000); 508 509 // Reduce thread wake frequency so that other threads can get 510 // a chance to run. 511 TEST_UTIL.getConfiguration().setInt(HConstants.THREAD_WAKE_FREQUENCY, 512 2 * 1000); 513 514 /**** configuration for testLogRollOnDatanodeDeath ****/ 515 // lower the namenode & datanode heartbeat so the namenode 516 // quickly detects datanode failures 517 TEST_UTIL.getConfiguration().setInt("dfs.namenode.heartbeat.recheck-interval", 5000); 518 TEST_UTIL.getConfiguration().setInt("dfs.heartbeat.interval", 1); 519 // the namenode might still try to choose the recently-dead datanode 520 // for a pipeline, so try to a new pipeline multiple times 521 TEST_UTIL.getConfiguration().setInt("dfs.client.block.write.retries", 30); 522 TEST_UTIL.getConfiguration().setInt( 523 "hbase.regionserver.hlog.tolerable.lowreplication", 2); 524 TEST_UTIL.getConfiguration().setInt( 525 "hbase.regionserver.hlog.lowreplication.rolllimit", 3); 526 } 527 528 private HRegionServer startAndWriteData(TableName tableName, byte[] value) 529 throws IOException, InterruptedException { 530 // When the hbase:meta table can be opened, the region servers are running 531 TEST_UTIL.getConnection().getTable(TableName.META_TABLE_NAME).close(); 532 533 // Create the test table and open it 534 HTableDescriptor desc = new HTableDescriptor(tableName); 535 desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); 536 admin.createTable(desc); 537 Table table = TEST_UTIL.getConnection().getTable(tableName); 538 539 HRegionServer regionServer = TEST_UTIL.getRSForFirstRegionInTable(tableName); 540 for (int i = 1; i <= 256; i++) { // 256 writes should cause 8 log rolls 541 Put put = new Put(Bytes.toBytes("row" + String.format("%1$04d", i))); 542 put.addColumn(HConstants.CATALOG_FAMILY, null, value); 543 table.put(put); 544 if (i % 32 == 0) { 545 // After every 32 writes sleep to let the log roller run 546 try { 547 Thread.sleep(2000); 548 } catch (InterruptedException e) { 549 // continue 550 } 551 } 552 } 553 554 table.close(); 555 return regionServer; 556 } 557 558 /** 559 * Check that we have an exception if the cluster is not there. 560 */ 561 @Test 562 public void testCheckHBaseAvailableWithoutCluster() { 563 Configuration conf = new Configuration(TEST_UTIL.getConfiguration()); 564 565 // Change the ZK address to go to something not used. 566 conf.setInt(HConstants.ZOOKEEPER_CLIENT_PORT, 567 conf.getInt(HConstants.ZOOKEEPER_CLIENT_PORT, 9999)+10); 568 569 long start = System.currentTimeMillis(); 570 try { 571 HBaseAdmin.available(conf); 572 assertTrue(false); 573 } catch (ZooKeeperConnectionException ignored) { 574 } catch (IOException ignored) { 575 } 576 long end = System.currentTimeMillis(); 577 578 LOG.info("It took "+(end-start)+" ms to find out that" + 579 " HBase was not available"); 580 } 581 582 @Test 583 public void testDisableCatalogTable() throws Exception { 584 try { 585 this.admin.disableTable(TableName.META_TABLE_NAME); 586 fail("Expected to throw ConstraintException"); 587 } catch (ConstraintException e) { 588 } 589 // Before the fix for HBASE-6146, the below table creation was failing as the hbase:meta table 590 // actually getting disabled by the disableTable() call. 591 HTableDescriptor htd = 592 new HTableDescriptor(TableName.valueOf(Bytes.toBytes(name.getMethodName()))); 593 HColumnDescriptor hcd = new HColumnDescriptor(Bytes.toBytes("cf1")); 594 htd.addFamily(hcd); 595 TEST_UTIL.getHBaseAdmin().createTable(htd); 596 } 597 598 @Test 599 public void testIsEnabledOrDisabledOnUnknownTable() throws Exception { 600 try { 601 admin.isTableEnabled(TableName.valueOf(name.getMethodName())); 602 fail("Test should fail if isTableEnabled called on unknown table."); 603 } catch (IOException e) { 604 } 605 606 try { 607 admin.isTableDisabled(TableName.valueOf(name.getMethodName())); 608 fail("Test should fail if isTableDisabled called on unknown table."); 609 } catch (IOException e) { 610 } 611 } 612 613 @Test 614 public void testGetRegion() throws Exception { 615 // We use actual HBaseAdmin instance instead of going via Admin interface in 616 // here because makes use of an internal HBA method (TODO: Fix.). 617 HBaseAdmin rawAdmin = TEST_UTIL.getHBaseAdmin(); 618 619 final TableName tableName = TableName.valueOf(name.getMethodName()); 620 LOG.info("Started " + tableName); 621 Table t = TEST_UTIL.createMultiRegionTable(tableName, HConstants.CATALOG_FAMILY); 622 623 try (RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(tableName)) { 624 HRegionLocation regionLocation = locator.getRegionLocation(Bytes.toBytes("mmm")); 625 RegionInfo region = regionLocation.getRegionInfo(); 626 byte[] regionName = region.getRegionName(); 627 Pair<RegionInfo, ServerName> pair = rawAdmin.getRegion(regionName); 628 assertTrue(Bytes.equals(regionName, pair.getFirst().getRegionName())); 629 pair = rawAdmin.getRegion(region.getEncodedNameAsBytes()); 630 assertTrue(Bytes.equals(regionName, pair.getFirst().getRegionName())); 631 } 632 } 633 634 @Test 635 public void testBalancer() throws Exception { 636 boolean initialState = admin.isBalancerEnabled(); 637 638 // Start the balancer, wait for it. 639 boolean prevState = admin.setBalancerRunning(!initialState, true); 640 641 // The previous state should be the original state we observed 642 assertEquals(initialState, prevState); 643 644 // Current state should be opposite of the original 645 assertEquals(!initialState, admin.isBalancerEnabled()); 646 647 // Reset it back to what it was 648 prevState = admin.setBalancerRunning(initialState, true); 649 650 // The previous state should be the opposite of the initial state 651 assertEquals(!initialState, prevState); 652 // Current state should be the original state again 653 assertEquals(initialState, admin.isBalancerEnabled()); 654 } 655 656 @Test 657 public void testRegionNormalizer() throws Exception { 658 boolean initialState = admin.isNormalizerEnabled(); 659 660 // flip state 661 boolean prevState = admin.setNormalizerRunning(!initialState); 662 663 // The previous state should be the original state we observed 664 assertEquals(initialState, prevState); 665 666 // Current state should be opposite of the original 667 assertEquals(!initialState, admin.isNormalizerEnabled()); 668 669 // Reset it back to what it was 670 prevState = admin.setNormalizerRunning(initialState); 671 672 // The previous state should be the opposite of the initial state 673 assertEquals(!initialState, prevState); 674 // Current state should be the original state again 675 assertEquals(initialState, admin.isNormalizerEnabled()); 676 } 677 678 @Test 679 public void testAbortProcedureFail() throws Exception { 680 Random randomGenerator = new Random(); 681 long procId = randomGenerator.nextLong(); 682 683 boolean abortResult = admin.abortProcedure(procId, true); 684 assertFalse(abortResult); 685 } 686 687 @Test 688 public void testGetProcedures() throws Exception { 689 String procList = admin.getProcedures(); 690 assertTrue(procList.startsWith("[")); 691 } 692 693 @Test 694 public void testGetLocks() throws Exception { 695 String lockList = admin.getLocks(); 696 assertTrue(lockList.startsWith("[")); 697 } 698 699 @Test 700 public void testDecommissionRegionServers() throws Exception { 701 List<ServerName> decommissionedRegionServers = admin.listDecommissionedRegionServers(); 702 assertTrue(decommissionedRegionServers.isEmpty()); 703 704 final TableName tableName = TableName.valueOf(name.getMethodName()); 705 TEST_UTIL.createMultiRegionTable(tableName, Bytes.toBytes("f"), 6); 706 707 ArrayList<ServerName> clusterRegionServers = 708 new ArrayList<>(admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)) 709 .getLiveServerMetrics().keySet()); 710 711 assertEquals(3, clusterRegionServers.size()); 712 713 HashMap<ServerName, List<RegionInfo>> serversToDecommssion = new HashMap<>(); 714 // Get a server that has regions. We will decommission two of the servers, 715 // leaving one online. 716 int i; 717 for (i = 0; i < clusterRegionServers.size(); i++) { 718 List<RegionInfo> regionsOnServer = admin.getRegions(clusterRegionServers.get(i)); 719 if (regionsOnServer.size() > 0) { 720 serversToDecommssion.put(clusterRegionServers.get(i), regionsOnServer); 721 break; 722 } 723 } 724 725 clusterRegionServers.remove(i); 726 // Get another server to decommission. 727 serversToDecommssion.put(clusterRegionServers.get(0), 728 admin.getRegions(clusterRegionServers.get(0))); 729 730 ServerName remainingServer = clusterRegionServers.get(1); 731 732 // Decommission 733 admin.decommissionRegionServers(new ArrayList<ServerName>(serversToDecommssion.keySet()), true); 734 assertEquals(2, admin.listDecommissionedRegionServers().size()); 735 736 // Verify the regions have been off the decommissioned servers, all on the one 737 // remaining server. 738 for (ServerName server : serversToDecommssion.keySet()) { 739 for (RegionInfo region : serversToDecommssion.get(server)) { 740 TEST_UTIL.assertRegionOnServer(region, remainingServer, 10000); 741 } 742 } 743 744 // Recommission and load the regions. 745 for (ServerName server : serversToDecommssion.keySet()) { 746 List<byte[]> encodedRegionNames = serversToDecommssion.get(server).stream() 747 .map(region -> region.getEncodedNameAsBytes()).collect(Collectors.toList()); 748 admin.recommissionRegionServer(server, encodedRegionNames); 749 } 750 assertTrue(admin.listDecommissionedRegionServers().isEmpty()); 751 // Verify the regions have been moved to the recommissioned servers 752 for (ServerName server : serversToDecommssion.keySet()) { 753 for (RegionInfo region : serversToDecommssion.get(server)) { 754 TEST_UTIL.assertRegionOnServer(region, server, 10000); 755 } 756 } 757 } 758}