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