2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org
.apache
.hadoop
.hbase
.client
;
20 import static org
.junit
.Assert
.assertEquals
;
21 import static org
.junit
.Assert
.assertFalse
;
22 import static org
.junit
.Assert
.assertTrue
;
23 import static org
.junit
.Assert
.fail
;
25 import java
.io
.IOException
;
26 import java
.util
.ArrayList
;
27 import java
.util
.Collection
;
28 import java
.util
.EnumSet
;
29 import java
.util
.HashMap
;
30 import java
.util
.HashSet
;
31 import java
.util
.List
;
32 import java
.util
.Random
;
33 import java
.util
.concurrent
.atomic
.AtomicInteger
;
34 import java
.util
.stream
.Collectors
;
35 import org
.apache
.hadoop
.hbase
.ClusterMetrics
.Option
;
36 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
37 import org
.apache
.hadoop
.hbase
.HConstants
;
38 import org
.apache
.hadoop
.hbase
.HTableDescriptor
;
39 import org
.apache
.hadoop
.hbase
.MiniHBaseCluster
;
40 import org
.apache
.hadoop
.hbase
.ServerName
;
41 import org
.apache
.hadoop
.hbase
.TableExistsException
;
42 import org
.apache
.hadoop
.hbase
.TableName
;
43 import org
.apache
.hadoop
.hbase
.TableNotDisabledException
;
44 import org
.apache
.hadoop
.hbase
.TableNotEnabledException
;
45 import org
.apache
.hadoop
.hbase
.TableNotFoundException
;
46 import org
.apache
.hadoop
.hbase
.UnknownRegionException
;
47 import org
.apache
.hadoop
.hbase
.Waiter
.Predicate
;
48 import org
.apache
.hadoop
.hbase
.constraint
.ConstraintException
;
49 import org
.apache
.hadoop
.hbase
.master
.HMaster
;
50 import org
.apache
.hadoop
.hbase
.master
.assignment
.AssignmentManager
;
51 import org
.apache
.hadoop
.hbase
.regionserver
.HRegion
;
52 import org
.apache
.hadoop
.hbase
.regionserver
.HRegionServer
;
53 import org
.apache
.hadoop
.hbase
.regionserver
.HStore
;
54 import org
.apache
.hadoop
.hbase
.testclassification
.ClientTests
;
55 import org
.apache
.hadoop
.hbase
.testclassification
.LargeTests
;
56 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
57 import org
.apache
.hadoop
.hbase
.util
.FutureUtils
;
58 import org
.apache
.hadoop
.hbase
.wal
.AbstractFSWALProvider
;
59 import org
.junit
.Assert
;
60 import org
.junit
.ClassRule
;
61 import org
.junit
.Test
;
62 import org
.junit
.experimental
.categories
.Category
;
63 import org
.slf4j
.Logger
;
64 import org
.slf4j
.LoggerFactory
;
66 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.ProtobufUtil
;
67 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.RequestConverter
;
70 * Class to test HBaseAdmin.
71 * Spins up the minicluster once at test start and then takes it down afterward.
72 * Add any testing of HBaseAdmin functionality here.
74 @Category({LargeTests
.class, ClientTests
.class})
75 public class TestAdmin2
extends TestAdminBase
{
78 public static final HBaseClassTestRule CLASS_RULE
=
79 HBaseClassTestRule
.forClass(TestAdmin2
.class);
81 private static final Logger LOG
= LoggerFactory
.getLogger(TestAdmin2
.class);
84 public void testCreateBadTables() throws IOException
{
87 ADMIN
.createTable(new HTableDescriptor(TableName
.META_TABLE_NAME
));
88 } catch(TableExistsException e
) {
91 assertTrue("Unexcepted exception message " + msg
, msg
!= null &&
92 msg
.startsWith(TableExistsException
.class.getName()) &&
93 msg
.contains(TableName
.META_TABLE_NAME
.getNameAsString()));
95 // Now try and do concurrent creation with a bunch of threads.
96 TableDescriptorBuilder
.ModifyableTableDescriptor tableDescriptor
=
97 new TableDescriptorBuilder
.ModifyableTableDescriptor(
98 TableName
.valueOf(name
.getMethodName()));
99 ColumnFamilyDescriptor familyDescriptor
=
100 new ColumnFamilyDescriptorBuilder
.ModifyableColumnFamilyDescriptor(
101 HConstants
.CATALOG_FAMILY
);
102 tableDescriptor
.setColumnFamily(familyDescriptor
);
104 Thread
[] threads
= new Thread
[count
];
105 final AtomicInteger successes
= new AtomicInteger(0);
106 final AtomicInteger failures
= new AtomicInteger(0);
107 final Admin localAdmin
= ADMIN
;
108 for (int i
= 0; i
< count
; i
++) {
109 threads
[i
] = new Thread(Integer
.toString(i
)) {
113 localAdmin
.createTable(tableDescriptor
);
114 successes
.incrementAndGet();
115 } catch (TableExistsException e
) {
116 failures
.incrementAndGet();
117 } catch (IOException e
) {
118 throw new RuntimeException("Failed threaded create" + getName(), e
);
123 for (int i
= 0; i
< count
; i
++) {
126 for (int i
= 0; i
< count
; i
++) {
127 while(threads
[i
].isAlive()) {
130 } catch (InterruptedException e
) {
135 // All threads are now dead. Count up how many tables were created and
136 // how many failed w/ appropriate exception.
137 assertEquals(1, successes
.get());
138 assertEquals(count
- 1, failures
.get());
142 * Test for hadoop-1581 'HBASE: Unopenable tablename bug'.
146 public void testTableNameClash() throws Exception
{
147 final String name
= this.name
.getMethodName();
148 TableDescriptorBuilder
.ModifyableTableDescriptor tableDescriptor1
=
149 new TableDescriptorBuilder
.ModifyableTableDescriptor(
150 TableName
.valueOf(name
+ "SOMEUPPERCASE"));
151 TableDescriptorBuilder
.ModifyableTableDescriptor tableDescriptor2
=
152 new TableDescriptorBuilder
.ModifyableTableDescriptor(TableName
.valueOf(name
));
153 tableDescriptor1
.setColumnFamily(
154 new ColumnFamilyDescriptorBuilder
.ModifyableColumnFamilyDescriptor(
155 HConstants
.CATALOG_FAMILY
));
156 tableDescriptor2
.setColumnFamily(
157 new ColumnFamilyDescriptorBuilder
.ModifyableColumnFamilyDescriptor(
158 HConstants
.CATALOG_FAMILY
));
159 ADMIN
.createTable(tableDescriptor1
);
160 ADMIN
.createTable(tableDescriptor2
);
161 // Before fix, below would fail throwing a NoServerForRegionException.
162 TEST_UTIL
.getConnection().getTable(tableDescriptor2
.getTableName()).close();
166 * HMaster.createTable used to be kind of synchronous call
167 * Thus creating of table with lots of regions can cause RPC timeout
168 * After the fix to make createTable truly async, RPC timeout shouldn't be an
172 public void testCreateTableRPCTimeOut() throws Exception
{
173 final String name
= this.name
.getMethodName();
174 int oldTimeout
= TEST_UTIL
.getConfiguration().
175 getInt(HConstants
.HBASE_RPC_TIMEOUT_KEY
, HConstants
.DEFAULT_HBASE_RPC_TIMEOUT
);
176 TEST_UTIL
.getConfiguration().setInt(HConstants
.HBASE_RPC_TIMEOUT_KEY
, 1500);
178 int expectedRegions
= 100;
179 // Use 80 bit numbers to make sure we aren't limited
180 byte [] startKey
= { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
181 byte [] endKey
= { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
182 Admin hbaseadmin
= TEST_UTIL
.getAdmin();
183 TableDescriptorBuilder
.ModifyableTableDescriptor tableDescriptor
=
184 new TableDescriptorBuilder
.ModifyableTableDescriptor(TableName
.valueOf(name
));
185 tableDescriptor
.setColumnFamily(
186 new ColumnFamilyDescriptorBuilder
.ModifyableColumnFamilyDescriptor(
187 HConstants
.CATALOG_FAMILY
));
188 hbaseadmin
.createTable(tableDescriptor
, startKey
, endKey
, expectedRegions
);
190 TEST_UTIL
.getConfiguration().setInt(HConstants
.HBASE_RPC_TIMEOUT_KEY
, oldTimeout
);
195 * Test read only tables
199 public void testReadOnlyTable() throws Exception
{
200 final TableName name
= TableName
.valueOf(this.name
.getMethodName());
201 Table table
= TEST_UTIL
.createTable(name
, HConstants
.CATALOG_FAMILY
);
202 byte[] value
= Bytes
.toBytes("somedata");
203 // This used to use an empty row... That must have been a bug
204 Put put
= new Put(value
);
205 put
.addColumn(HConstants
.CATALOG_FAMILY
, HConstants
.CATALOG_FAMILY
, value
);
211 * Test that user table names can contain '-' and '.' so long as they do not
212 * start with same. HBASE-771
215 public void testTableNames() throws IOException
{
216 byte[][] illegalNames
= new byte[][] {
217 Bytes
.toBytes("-bad"),
218 Bytes
.toBytes(".bad")
220 for (byte[] illegalName
: illegalNames
) {
222 new HTableDescriptor(TableName
.valueOf(illegalName
));
223 throw new IOException("Did not detect '" +
224 Bytes
.toString(illegalName
) + "' as an illegal user table name");
225 } catch (IllegalArgumentException e
) {
229 byte[] legalName
= Bytes
.toBytes("g-oo.d");
231 new HTableDescriptor(TableName
.valueOf(legalName
));
232 } catch (IllegalArgumentException e
) {
233 throw new IOException("Legal user table name: '" +
234 Bytes
.toString(legalName
) + "' caused IllegalArgumentException: " +
242 @Test (expected
=TableExistsException
.class)
243 public void testTableExistsExceptionWithATable() throws IOException
{
244 final TableName name
= TableName
.valueOf(this.name
.getMethodName());
245 TEST_UTIL
.createTable(name
, HConstants
.CATALOG_FAMILY
).close();
246 TEST_UTIL
.createTable(name
, HConstants
.CATALOG_FAMILY
);
250 * Can't disable a table if the table isn't in enabled state
252 @Test (expected
=TableNotEnabledException
.class)
253 public void testTableNotEnabledExceptionWithATable() throws IOException
{
254 final TableName name
= TableName
.valueOf(this.name
.getMethodName());
255 TEST_UTIL
.createTable(name
, HConstants
.CATALOG_FAMILY
).close();
256 ADMIN
.disableTable(name
);
257 ADMIN
.disableTable(name
);
261 * Can't enable a table if the table isn't in disabled state
263 @Test(expected
= TableNotDisabledException
.class)
264 public void testTableNotDisabledExceptionWithATable() throws IOException
{
265 final TableName name
= TableName
.valueOf(this.name
.getMethodName());
266 try (Table t
= TEST_UTIL
.createTable(name
, HConstants
.CATALOG_FAMILY
)) {
267 ADMIN
.enableTable(name
);
274 @Test(expected
= TableNotFoundException
.class)
275 public void testTableNotFoundExceptionWithoutAnyTables() throws IOException
{
276 TableName tableName
= TableName
.valueOf("testTableNotFoundExceptionWithoutAnyTables");
277 try (Table ht
= TEST_UTIL
.getConnection().getTable(tableName
)) {
278 ht
.get(new Get(Bytes
.toBytes("e")));
283 public void testShouldUnassignTheRegion() throws Exception
{
284 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
285 createTableWithDefaultConf(tableName
);
287 RegionInfo info
= null;
288 HRegionServer rs
= TEST_UTIL
.getRSForFirstRegionInTable(tableName
);
289 List
<RegionInfo
> onlineRegions
= ProtobufUtil
.getOnlineRegions(rs
.getRSRpcServices());
290 for (RegionInfo regionInfo
: onlineRegions
) {
291 if (!regionInfo
.getTable().isSystemTable()) {
293 ADMIN
.unassign(regionInfo
.getRegionName(), true);
296 boolean isInList
= ProtobufUtil
.getOnlineRegions(
297 rs
.getRSRpcServices()).contains(info
);
298 long timeout
= System
.currentTimeMillis() + 10000;
299 while ((System
.currentTimeMillis() < timeout
) && (isInList
)) {
301 isInList
= ProtobufUtil
.getOnlineRegions(
302 rs
.getRSRpcServices()).contains(info
);
305 assertFalse("The region should not be present in online regions list.",
310 public void testCloseRegionIfInvalidRegionNameIsPassed() throws Exception
{
311 final String name
= this.name
.getMethodName();
312 byte[] tableName
= Bytes
.toBytes(name
);
313 createTableWithDefaultConf(tableName
);
315 RegionInfo info
= null;
316 HRegionServer rs
= TEST_UTIL
.getRSForFirstRegionInTable(TableName
.valueOf(tableName
));
317 List
<RegionInfo
> onlineRegions
= ProtobufUtil
.getOnlineRegions(rs
.getRSRpcServices());
318 for (RegionInfo regionInfo
: onlineRegions
) {
319 if (!regionInfo
.isMetaRegion()) {
320 if (regionInfo
.getRegionNameAsString().contains(name
)) {
323 ADMIN
.unassign(Bytes
.toBytes("sample"), true);
324 } catch (UnknownRegionException nsre
) {
325 // expected, ignore it
330 onlineRegions
= ProtobufUtil
.getOnlineRegions(rs
.getRSRpcServices());
331 assertTrue("The region should be present in online regions list.",
332 onlineRegions
.contains(info
));
336 public void testCloseRegionThatFetchesTheHRIFromMeta() throws Exception
{
337 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
338 createTableWithDefaultConf(tableName
);
340 RegionInfo info
= null;
341 HRegionServer rs
= TEST_UTIL
.getRSForFirstRegionInTable(tableName
);
342 List
<RegionInfo
> onlineRegions
= ProtobufUtil
.getOnlineRegions(rs
.getRSRpcServices());
343 for (RegionInfo regionInfo
: onlineRegions
) {
344 if (!regionInfo
.isMetaRegion()) {
345 if (regionInfo
.getRegionNameAsString().contains("TestHBACloseRegion2")) {
347 ADMIN
.unassign(regionInfo
.getRegionName(), true);
352 boolean isInList
= ProtobufUtil
.getOnlineRegions(
353 rs
.getRSRpcServices()).contains(info
);
354 long timeout
= System
.currentTimeMillis() + 10000;
355 while ((System
.currentTimeMillis() < timeout
) && (isInList
)) {
357 isInList
= ProtobufUtil
.getOnlineRegions(
358 rs
.getRSRpcServices()).contains(info
);
361 assertFalse("The region should not be present in online regions list.",
365 private Admin
createTable(TableName tableName
) throws IOException
{
366 Admin admin
= TEST_UTIL
.getAdmin();
368 TableDescriptorBuilder tableDescriptorBuilder
=
369 TableDescriptorBuilder
.newBuilder(tableName
);
370 ColumnFamilyDescriptor columnFamilyDescriptor
=
371 ColumnFamilyDescriptorBuilder
.newBuilder(Bytes
.toBytes("value")).build();
373 tableDescriptorBuilder
.setColumnFamily(columnFamilyDescriptor
);
374 admin
.createTable(tableDescriptorBuilder
.build());
378 private void createTableWithDefaultConf(byte[] TABLENAME
) throws IOException
{
379 createTableWithDefaultConf(TableName
.valueOf(TABLENAME
));
382 private void createTableWithDefaultConf(TableName TABLENAME
) throws IOException
{
383 TableDescriptorBuilder tableDescriptorBuilder
=
384 TableDescriptorBuilder
.newBuilder(TABLENAME
);
385 ColumnFamilyDescriptor columnFamilyDescriptor
=
386 ColumnFamilyDescriptorBuilder
.newBuilder(Bytes
.toBytes("value")).build();
387 tableDescriptorBuilder
.setColumnFamily(columnFamilyDescriptor
);
389 ADMIN
.createTable(tableDescriptorBuilder
.build());
396 public void testGetTableRegions() throws IOException
{
397 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
399 int expectedRegions
= 10;
401 // Use 80 bit numbers to make sure we aren't limited
402 byte [] startKey
= { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
403 byte [] endKey
= { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
406 TableDescriptorBuilder
.ModifyableTableDescriptor tableDescriptor
=
407 new TableDescriptorBuilder
.ModifyableTableDescriptor(tableName
);
408 tableDescriptor
.setColumnFamily(
409 new ColumnFamilyDescriptorBuilder
.ModifyableColumnFamilyDescriptor(
410 HConstants
.CATALOG_FAMILY
));
411 ADMIN
.createTable(tableDescriptor
, startKey
, endKey
, expectedRegions
);
413 List
<RegionInfo
> RegionInfos
= ADMIN
.getRegions(tableName
);
415 assertEquals("Tried to create " + expectedRegions
+ " regions " +
416 "but only found " + RegionInfos
.size(),
417 expectedRegions
, RegionInfos
.size());
421 public void testMoveToPreviouslyAssignedRS() throws IOException
, InterruptedException
{
422 MiniHBaseCluster cluster
= TEST_UTIL
.getHBaseCluster();
423 HMaster master
= cluster
.getMaster();
424 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
425 Admin localAdmin
= createTable(tableName
);
426 List
<RegionInfo
> tableRegions
= localAdmin
.getRegions(tableName
);
427 RegionInfo hri
= tableRegions
.get(0);
428 AssignmentManager am
= master
.getAssignmentManager();
429 ServerName server
= am
.getRegionStates().getRegionServerOfRegion(hri
);
430 localAdmin
.move(hri
.getEncodedNameAsBytes(), server
);
431 assertEquals("Current region server and region server before move should be same.", server
,
432 am
.getRegionStates().getRegionServerOfRegion(hri
));
436 public void testWALRollWriting() throws Exception
{
437 setUpforLogRolling();
438 String className
= this.getClass().getName();
439 StringBuilder v
= new StringBuilder(className
);
440 while (v
.length() < 1000) {
443 byte[] value
= Bytes
.toBytes(v
.toString());
444 HRegionServer regionServer
= startAndWriteData(TableName
.valueOf(name
.getMethodName()), value
);
445 LOG
.info("after writing there are "
446 + AbstractFSWALProvider
.getNumRolledLogFiles(regionServer
.getWAL(null)) + " log files");
449 for (HRegion r
: regionServer
.getOnlineRegionsLocalContext()) {
452 ADMIN
.rollWALWriter(regionServer
.getServerName());
453 int count
= AbstractFSWALProvider
.getNumRolledLogFiles(regionServer
.getWAL(null));
454 LOG
.info("after flushing all regions and rolling logs there are " +
455 count
+ " log files");
456 assertTrue(("actual count: " + count
), count
<= 2);
459 private void setUpforLogRolling() {
460 // Force a region split after every 768KB
461 TEST_UTIL
.getConfiguration().setLong(HConstants
.HREGION_MAX_FILESIZE
,
464 // We roll the log after every 32 writes
465 TEST_UTIL
.getConfiguration().setInt("hbase.regionserver.maxlogentries", 32);
467 TEST_UTIL
.getConfiguration().setInt(
468 "hbase.regionserver.logroll.errors.tolerated", 2);
469 TEST_UTIL
.getConfiguration().setInt("hbase.rpc.timeout", 10 * 1000);
471 // For less frequently updated regions flush after every 2 flushes
472 TEST_UTIL
.getConfiguration().setInt(
473 "hbase.hregion.memstore.optionalflushcount", 2);
475 // We flush the cache after every 8192 bytes
476 TEST_UTIL
.getConfiguration().setInt(HConstants
.HREGION_MEMSTORE_FLUSH_SIZE
,
479 // Increase the amount of time between client retries
480 TEST_UTIL
.getConfiguration().setLong("hbase.client.pause", 10 * 1000);
482 // Reduce thread wake frequency so that other threads can get
484 TEST_UTIL
.getConfiguration().setInt(HConstants
.THREAD_WAKE_FREQUENCY
,
487 /**** configuration for testLogRollOnDatanodeDeath ****/
488 // lower the namenode & datanode heartbeat so the namenode
489 // quickly detects datanode failures
490 TEST_UTIL
.getConfiguration().setInt("dfs.namenode.heartbeat.recheck-interval", 5000);
491 TEST_UTIL
.getConfiguration().setInt("dfs.heartbeat.interval", 1);
492 // the namenode might still try to choose the recently-dead datanode
493 // for a pipeline, so try to a new pipeline multiple times
494 TEST_UTIL
.getConfiguration().setInt("dfs.client.block.write.retries", 30);
495 TEST_UTIL
.getConfiguration().setInt(
496 "hbase.regionserver.hlog.tolerable.lowreplication", 2);
497 TEST_UTIL
.getConfiguration().setInt(
498 "hbase.regionserver.hlog.lowreplication.rolllimit", 3);
501 private HRegionServer
startAndWriteData(TableName tableName
, byte[] value
)
502 throws IOException
, InterruptedException
{
503 // When the hbase:meta table can be opened, the region servers are running
504 TEST_UTIL
.getConnection().getTable(TableName
.META_TABLE_NAME
).close();
506 // Create the test table and open it
507 TableDescriptorBuilder
.ModifyableTableDescriptor tableDescriptor
=
508 new TableDescriptorBuilder
.ModifyableTableDescriptor(tableName
);
509 tableDescriptor
.setColumnFamily(
510 new ColumnFamilyDescriptorBuilder
.ModifyableColumnFamilyDescriptor(
511 HConstants
.CATALOG_FAMILY
));
512 ADMIN
.createTable(tableDescriptor
);
513 Table table
= TEST_UTIL
.getConnection().getTable(tableName
);
515 HRegionServer regionServer
= TEST_UTIL
.getRSForFirstRegionInTable(tableName
);
516 for (int i
= 1; i
<= 256; i
++) { // 256 writes should cause 8 log rolls
517 Put put
= new Put(Bytes
.toBytes("row" + String
.format("%1$04d", i
)));
518 put
.addColumn(HConstants
.CATALOG_FAMILY
, null, value
);
521 // After every 32 writes sleep to let the log roller run
524 } catch (InterruptedException e
) {
535 public void testDisableCatalogTable() throws Exception
{
537 ADMIN
.disableTable(TableName
.META_TABLE_NAME
);
538 fail("Expected to throw ConstraintException");
539 } catch (ConstraintException e
) {
541 // Before the fix for HBASE-6146, the below table creation was failing as the hbase:meta table
542 // actually getting disabled by the disableTable() call.
543 TableDescriptorBuilder
.ModifyableTableDescriptor tableDescriptor
=
544 new TableDescriptorBuilder
.ModifyableTableDescriptor(
545 TableName
.valueOf(Bytes
.toBytes(name
.getMethodName())));
546 ColumnFamilyDescriptor familyDescriptor
=
547 new ColumnFamilyDescriptorBuilder
.ModifyableColumnFamilyDescriptor(
548 Bytes
.toBytes("cf1"));
550 tableDescriptor
.setColumnFamily(familyDescriptor
);
551 TEST_UTIL
.getAdmin().createTable(tableDescriptor
);
555 public void testIsEnabledOrDisabledOnUnknownTable() throws Exception
{
557 ADMIN
.isTableEnabled(TableName
.valueOf(name
.getMethodName()));
558 fail("Test should fail if isTableEnabled called on unknown table.");
559 } catch (IOException e
) {
563 ADMIN
.isTableDisabled(TableName
.valueOf(name
.getMethodName()));
564 fail("Test should fail if isTableDisabled called on unknown table.");
565 } catch (IOException e
) {
570 public void testBalancer() throws Exception
{
571 boolean initialState
= ADMIN
.isBalancerEnabled();
573 // Start the balancer, wait for it.
574 boolean prevState
= ADMIN
.balancerSwitch(!initialState
, true);
576 // The previous state should be the original state we observed
577 assertEquals(initialState
, prevState
);
579 // Current state should be opposite of the original
580 assertEquals(!initialState
, ADMIN
.isBalancerEnabled());
582 // Reset it back to what it was
583 prevState
= ADMIN
.balancerSwitch(initialState
, true);
585 // The previous state should be the opposite of the initial state
586 assertEquals(!initialState
, prevState
);
587 // Current state should be the original state again
588 assertEquals(initialState
, ADMIN
.isBalancerEnabled());
592 public void testRegionNormalizer() throws Exception
{
593 boolean initialState
= ADMIN
.isNormalizerEnabled();
596 boolean prevState
= ADMIN
.normalizerSwitch(!initialState
);
598 // The previous state should be the original state we observed
599 assertEquals(initialState
, prevState
);
601 // Current state should be opposite of the original
602 assertEquals(!initialState
, ADMIN
.isNormalizerEnabled());
604 // Reset it back to what it was
605 prevState
= ADMIN
.normalizerSwitch(initialState
);
607 // The previous state should be the opposite of the initial state
608 assertEquals(!initialState
, prevState
);
609 // Current state should be the original state again
610 assertEquals(initialState
, ADMIN
.isNormalizerEnabled());
614 public void testAbortProcedureFail() throws Exception
{
615 Random randomGenerator
= new Random();
616 long procId
= randomGenerator
.nextLong();
618 boolean abortResult
= ADMIN
.abortProcedure(procId
, true);
619 assertFalse(abortResult
);
623 public void testGetProcedures() throws Exception
{
624 String procList
= ADMIN
.getProcedures();
625 assertTrue(procList
.startsWith("["));
629 public void testGetLocks() throws Exception
{
630 String lockList
= ADMIN
.getLocks();
631 assertTrue(lockList
.startsWith("["));
635 public void testDecommissionRegionServers() throws Exception
{
636 List
<ServerName
> decommissionedRegionServers
= ADMIN
.listDecommissionedRegionServers();
637 assertTrue(decommissionedRegionServers
.isEmpty());
639 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
640 TEST_UTIL
.createMultiRegionTable(tableName
, Bytes
.toBytes("f"), 6);
642 ArrayList
<ServerName
> clusterRegionServers
=
643 new ArrayList
<>(ADMIN
.getClusterMetrics(EnumSet
.of(Option
.LIVE_SERVERS
))
644 .getLiveServerMetrics().keySet());
646 assertEquals(3, clusterRegionServers
.size());
648 HashMap
<ServerName
, List
<RegionInfo
>> serversToDecommssion
= new HashMap
<>();
649 // Get a server that has meta online. We will decommission two of the servers,
650 // leaving one online.
652 for (i
= 0; i
< clusterRegionServers
.size(); i
++) {
653 List
<RegionInfo
> regionsOnServer
= ADMIN
.getRegions(clusterRegionServers
.get(i
));
654 if (ADMIN
.getRegions(clusterRegionServers
.get(i
)).stream().anyMatch(p
-> p
.isMetaRegion())) {
655 serversToDecommssion
.put(clusterRegionServers
.get(i
), regionsOnServer
);
660 clusterRegionServers
.remove(i
);
661 // Get another server to decommission.
662 serversToDecommssion
.put(clusterRegionServers
.get(0),
663 ADMIN
.getRegions(clusterRegionServers
.get(0)));
665 ServerName remainingServer
= clusterRegionServers
.get(1);
668 ADMIN
.decommissionRegionServers(new ArrayList
<ServerName
>(serversToDecommssion
.keySet()), true);
669 assertEquals(2, ADMIN
.listDecommissionedRegionServers().size());
671 // Verify the regions have been off the decommissioned servers, all on the one
673 for (ServerName server
: serversToDecommssion
.keySet()) {
674 for (RegionInfo region
: serversToDecommssion
.get(server
)) {
675 TEST_UTIL
.assertRegionOnServer(region
, remainingServer
, 10000);
679 // Recommission and load the regions.
680 for (ServerName server
: serversToDecommssion
.keySet()) {
681 List
<byte[]> encodedRegionNames
= serversToDecommssion
.get(server
).stream()
682 .map(region
-> region
.getEncodedNameAsBytes()).collect(Collectors
.toList());
683 ADMIN
.recommissionRegionServer(server
, encodedRegionNames
);
685 assertTrue(ADMIN
.listDecommissionedRegionServers().isEmpty());
686 // Verify the regions have been moved to the recommissioned servers
687 for (ServerName server
: serversToDecommssion
.keySet()) {
688 for (RegionInfo region
: serversToDecommssion
.get(server
)) {
689 TEST_UTIL
.assertRegionOnServer(region
, server
, 10000);
695 * TestCase for HBASE-21355
698 public void testGetRegionInfo() throws Exception
{
699 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
700 Table table
= TEST_UTIL
.createTable(tableName
, Bytes
.toBytes("f"));
701 for (int i
= 0; i
< 100; i
++) {
702 table
.put(new Put(Bytes
.toBytes(i
)).addColumn(Bytes
.toBytes("f"), Bytes
.toBytes("q"),
705 ADMIN
.flush(tableName
);
707 HRegionServer rs
= TEST_UTIL
.getRSForFirstRegionInTable(table
.getName());
708 List
<HRegion
> regions
= rs
.getRegions(tableName
);
709 Assert
.assertEquals(1, regions
.size());
711 HRegion region
= regions
.get(0);
712 byte[] regionName
= region
.getRegionInfo().getRegionName();
713 HStore store
= region
.getStore(Bytes
.toBytes("f"));
714 long expectedStoreFilesSize
= store
.getStorefilesSize();
715 Assert
.assertNotNull(store
);
716 Assert
.assertEquals(expectedStoreFilesSize
, store
.getSize());
717 for (int i
= 0; i
< 10; i
++) {
718 RegionInfo ri
= ProtobufUtil
719 .toRegionInfo(TEST_UTIL
.getAsyncConnection().getRegionServerAdmin(rs
.getServerName())
720 .getRegionInfo(RequestConverter
.buildGetRegionInfoRequest(regionName
)).get()
723 Assert
.assertEquals(region
.getRegionInfo(), ri
);
725 // Make sure that the store size is still the actual file system's store size.
726 Assert
.assertEquals(expectedStoreFilesSize
, store
.getSize());
729 // Test querying using the encoded name only. When encoded name passed,
730 // and the target server is the Master, we return the full region name.
732 ServerName sn
= null;
733 try (Admin admin
= TEST_UTIL
.getConnection().getAdmin()) {
734 sn
= admin
.getMaster();
736 RegionInfo ri
= region
.getRegionInfo();
737 testGetWithRegionName(sn
, ri
, ri
.getEncodedNameAsBytes());
738 testGetWithRegionName(sn
, ri
, ri
.getRegionName());
739 // Try querying meta encoded name.
740 ri
= RegionInfoBuilder
.FIRST_META_REGIONINFO
;
741 testGetWithRegionName(sn
, ri
, ri
.getEncodedNameAsBytes());
742 testGetWithRegionName(sn
, ri
, ri
.getRegionName());
746 * Do get of RegionInfo from Master using encoded region name.
748 private void testGetWithRegionName(ServerName sn
, RegionInfo inputRI
,
749 byte [] regionName
) throws IOException
{
750 RegionInfo ri
= ProtobufUtil
.toRegionInfo(FutureUtils
.get(
751 TEST_UTIL
.getAsyncConnection().getRegionServerAdmin(sn
).getRegionInfo(
752 ProtobufUtil
.getGetRegionInfoRequest(regionName
))).getRegionInfo());
753 assertEquals(inputRI
, ri
);
757 public void testTableSplitFollowedByModify() throws Exception
{
758 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
759 TEST_UTIL
.createTable(tableName
, Bytes
.toBytes("f"));
761 // get the original table region count
762 List
<RegionInfo
> regions
= ADMIN
.getRegions(tableName
);
763 int originalCount
= regions
.size();
764 assertEquals(1, originalCount
);
766 // split the table and wait until region count increases
767 ADMIN
.split(tableName
, Bytes
.toBytes(3));
768 TEST_UTIL
.waitFor(30000, new Predicate
<Exception
>() {
771 public boolean evaluate() throws Exception
{
772 return ADMIN
.getRegions(tableName
).size() > originalCount
;
776 // do some table modification
777 TableDescriptor tableDesc
= TableDescriptorBuilder
.newBuilder(ADMIN
.getDescriptor(tableName
))
778 .setMaxFileSize(11111111)
780 ADMIN
.modifyTable(tableDesc
);
781 assertEquals(11111111, ADMIN
.getDescriptor(tableName
).getMaxFileSize());
785 public void testTableMergeFollowedByModify() throws Exception
{
786 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
787 TEST_UTIL
.createTable(tableName
, new byte[][] { Bytes
.toBytes("f") },
788 new byte[][] { Bytes
.toBytes(3) });
790 // assert we have at least 2 regions in the table
791 List
<RegionInfo
> regions
= ADMIN
.getRegions(tableName
);
792 int originalCount
= regions
.size();
793 assertTrue(originalCount
>= 2);
795 byte[] nameOfRegionA
= regions
.get(0).getEncodedNameAsBytes();
796 byte[] nameOfRegionB
= regions
.get(1).getEncodedNameAsBytes();
798 // merge the table regions and wait until region count decreases
799 ADMIN
.mergeRegionsAsync(nameOfRegionA
, nameOfRegionB
, true);
800 TEST_UTIL
.waitFor(30000, new Predicate
<Exception
>() {
803 public boolean evaluate() throws Exception
{
804 return ADMIN
.getRegions(tableName
).size() < originalCount
;
808 // do some table modification
809 TableDescriptor tableDesc
= TableDescriptorBuilder
.newBuilder(ADMIN
.getDescriptor(tableName
))
810 .setMaxFileSize(11111111)
812 ADMIN
.modifyTable(tableDesc
);
813 assertEquals(11111111, ADMIN
.getDescriptor(tableName
).getMaxFileSize());
817 public void testSnapshotCleanupAsync() throws Exception
{
818 testSnapshotCleanup(false);
822 public void testSnapshotCleanupSync() throws Exception
{
823 testSnapshotCleanup(true);
826 private void testSnapshotCleanup(final boolean synchronous
) throws IOException
{
827 final boolean initialState
= ADMIN
.isSnapshotCleanupEnabled();
828 // Switch the snapshot auto cleanup state to opposite to initial state
829 boolean prevState
= ADMIN
.snapshotCleanupSwitch(!initialState
, synchronous
);
830 // The previous state should be the original state we observed
831 assertEquals(initialState
, prevState
);
832 // Current state should be opposite of the initial state
833 assertEquals(!initialState
, ADMIN
.isSnapshotCleanupEnabled());
834 // Reset the state back to what it was initially
835 prevState
= ADMIN
.snapshotCleanupSwitch(initialState
, synchronous
);
836 // The previous state should be the opposite of the initial state
837 assertEquals(!initialState
, prevState
);
838 // Current state should be the original state again
839 assertEquals(initialState
, ADMIN
.isSnapshotCleanupEnabled());
843 public void testSlowLogResponses() throws Exception
{
844 // get all live server names
845 Collection
<ServerName
> serverNames
= ADMIN
.getRegionServers();
846 List
<ServerName
> serverNameList
= new ArrayList
<>(serverNames
);
848 // clean up slowlog responses maintained in memory by RegionServers
849 List
<Boolean
> areSlowLogsCleared
= ADMIN
.clearSlowLogResponses(new HashSet
<>(serverNameList
));
851 int countFailedClearSlowResponse
= 0;
852 for (Boolean isSlowLogCleared
: areSlowLogsCleared
) {
853 if (!isSlowLogCleared
) {
854 ++countFailedClearSlowResponse
;
857 Assert
.assertEquals(countFailedClearSlowResponse
, 0);
859 SlowLogQueryFilter slowLogQueryFilter
= new SlowLogQueryFilter();
860 List
<SlowLogRecord
> slowLogRecords
= ADMIN
.getSlowLogResponses(new HashSet
<>(serverNames
),
863 // after cleanup of slowlog responses, total count of slowlog payloads should be 0
864 Assert
.assertEquals(slowLogRecords
.size(), 0);