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