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
.assertThrows
;
23 import static org
.junit
.Assert
.assertTrue
;
24 import static org
.junit
.Assert
.fail
;
26 import java
.io
.IOException
;
27 import java
.util
.ArrayList
;
28 import java
.util
.Collection
;
29 import java
.util
.Collections
;
30 import java
.util
.EnumSet
;
31 import java
.util
.HashMap
;
32 import java
.util
.HashSet
;
33 import java
.util
.List
;
34 import java
.util
.Random
;
35 import java
.util
.concurrent
.atomic
.AtomicInteger
;
36 import java
.util
.stream
.Collectors
;
37 import org
.apache
.hadoop
.hbase
.ClusterMetrics
.Option
;
38 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
39 import org
.apache
.hadoop
.hbase
.HConstants
;
40 import org
.apache
.hadoop
.hbase
.ServerName
;
41 import org
.apache
.hadoop
.hbase
.SingleProcessHBaseCluster
;
42 import org
.apache
.hadoop
.hbase
.TableExistsException
;
43 import org
.apache
.hadoop
.hbase
.TableName
;
44 import org
.apache
.hadoop
.hbase
.TableNotDisabledException
;
45 import org
.apache
.hadoop
.hbase
.TableNotEnabledException
;
46 import org
.apache
.hadoop
.hbase
.TableNotFoundException
;
47 import org
.apache
.hadoop
.hbase
.UnknownRegionException
;
48 import org
.apache
.hadoop
.hbase
.Waiter
.Predicate
;
49 import org
.apache
.hadoop
.hbase
.constraint
.ConstraintException
;
50 import org
.apache
.hadoop
.hbase
.master
.HMaster
;
51 import org
.apache
.hadoop
.hbase
.master
.assignment
.AssignmentManager
;
52 import org
.apache
.hadoop
.hbase
.regionserver
.HRegion
;
53 import org
.apache
.hadoop
.hbase
.regionserver
.HRegionServer
;
54 import org
.apache
.hadoop
.hbase
.regionserver
.HStore
;
55 import org
.apache
.hadoop
.hbase
.testclassification
.ClientTests
;
56 import org
.apache
.hadoop
.hbase
.testclassification
.LargeTests
;
57 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
58 import org
.apache
.hadoop
.hbase
.util
.EnvironmentEdgeManager
;
59 import org
.apache
.hadoop
.hbase
.util
.FutureUtils
;
60 import org
.apache
.hadoop
.hbase
.wal
.AbstractFSWALProvider
;
61 import org
.junit
.Assert
;
62 import org
.junit
.ClassRule
;
63 import org
.junit
.Test
;
64 import org
.junit
.experimental
.categories
.Category
;
65 import org
.slf4j
.Logger
;
66 import org
.slf4j
.LoggerFactory
;
68 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.ProtobufUtil
;
69 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.RequestConverter
;
72 * Class to test HBaseAdmin.
73 * Spins up the minicluster once at test start and then takes it down afterward.
74 * Add any testing of HBaseAdmin functionality here.
76 @Category({LargeTests
.class, ClientTests
.class})
77 public class TestAdmin2
extends TestAdminBase
{
80 public static final HBaseClassTestRule CLASS_RULE
=
81 HBaseClassTestRule
.forClass(TestAdmin2
.class);
83 private static final Logger LOG
= LoggerFactory
.getLogger(TestAdmin2
.class);
86 public void testCreateBadTables() throws IOException
{
89 ADMIN
.createTable(TableDescriptorBuilder
.newBuilder(TableName
.META_TABLE_NAME
).build());
90 } catch (TableExistsException e
) {
93 assertTrue("Unexcepted exception message " + msg
, msg
!= null &&
94 msg
.startsWith(TableExistsException
.class.getName()) &&
95 msg
.contains(TableName
.META_TABLE_NAME
.getNameAsString()));
97 // Now try and do concurrent creation with a bunch of threads.
98 TableDescriptor tableDescriptor
=
99 TableDescriptorBuilder
.newBuilder(TableName
.valueOf(name
.getMethodName()))
100 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(HConstants
.CATALOG_FAMILY
)).build();
102 Thread
[] threads
= new Thread
[count
];
103 final AtomicInteger successes
= new AtomicInteger(0);
104 final AtomicInteger failures
= new AtomicInteger(0);
105 final Admin localAdmin
= ADMIN
;
106 for (int i
= 0; i
< count
; i
++) {
107 threads
[i
] = new Thread(Integer
.toString(i
)) {
111 localAdmin
.createTable(tableDescriptor
);
112 successes
.incrementAndGet();
113 } catch (TableExistsException e
) {
114 failures
.incrementAndGet();
115 } catch (IOException e
) {
116 throw new RuntimeException("Failed threaded create" + getName(), e
);
121 for (int i
= 0; i
< count
; i
++) {
124 for (int i
= 0; i
< count
; i
++) {
125 while(threads
[i
].isAlive()) {
128 } catch (InterruptedException e
) {
133 // All threads are now dead. Count up how many tables were created and
134 // how many failed w/ appropriate exception.
135 assertEquals(1, successes
.get());
136 assertEquals(count
- 1, failures
.get());
140 * Test for hadoop-1581 'HBASE: Unopenable tablename bug'.
143 public void testTableNameClash() throws Exception
{
144 final String name
= this.name
.getMethodName();
145 TableDescriptor tableDescriptor1
=
146 TableDescriptorBuilder
.newBuilder(TableName
.valueOf(name
+ "SOMEUPPERCASE"))
147 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(HConstants
.CATALOG_FAMILY
)).build();
148 TableDescriptor tableDescriptor2
= TableDescriptorBuilder
.newBuilder(TableName
.valueOf(name
))
149 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(HConstants
.CATALOG_FAMILY
)).build();
150 ADMIN
.createTable(tableDescriptor1
);
151 ADMIN
.createTable(tableDescriptor2
);
152 // Before fix, below would fail throwing a NoServerForRegionException.
153 TEST_UTIL
.getConnection().getTable(tableDescriptor2
.getTableName()).close();
157 * HMaster.createTable used to be kind of synchronous call
158 * Thus creating of table with lots of regions can cause RPC timeout
159 * After the fix to make createTable truly async, RPC timeout shouldn't be an
163 public void testCreateTableRPCTimeOut() throws Exception
{
164 final String name
= this.name
.getMethodName();
165 int oldTimeout
= TEST_UTIL
.getConfiguration().
166 getInt(HConstants
.HBASE_RPC_TIMEOUT_KEY
, HConstants
.DEFAULT_HBASE_RPC_TIMEOUT
);
167 TEST_UTIL
.getConfiguration().setInt(HConstants
.HBASE_RPC_TIMEOUT_KEY
, 1500);
169 int expectedRegions
= 100;
170 // Use 80 bit numbers to make sure we aren't limited
171 byte [] startKey
= { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
172 byte [] endKey
= { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
173 Admin hbaseadmin
= TEST_UTIL
.getAdmin();
174 TableDescriptor tableDescriptor
= TableDescriptorBuilder
.newBuilder(TableName
.valueOf(name
))
175 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(HConstants
.CATALOG_FAMILY
)).build();
176 hbaseadmin
.createTable(tableDescriptor
, startKey
, endKey
, expectedRegions
);
178 TEST_UTIL
.getConfiguration().setInt(HConstants
.HBASE_RPC_TIMEOUT_KEY
, oldTimeout
);
183 * Test read only tables
187 public void testReadOnlyTable() throws Exception
{
188 final TableName name
= TableName
.valueOf(this.name
.getMethodName());
189 Table table
= TEST_UTIL
.createTable(name
, HConstants
.CATALOG_FAMILY
);
190 byte[] value
= Bytes
.toBytes("somedata");
191 // This used to use an empty row... That must have been a bug
192 Put put
= new Put(value
);
193 put
.addColumn(HConstants
.CATALOG_FAMILY
, HConstants
.CATALOG_FAMILY
, value
);
199 * Test that user table names can contain '-' and '.' so long as they do not
200 * start with same. HBASE-771
203 public void testTableNames() throws IOException
{
204 byte[][] illegalNames
= new byte[][] { Bytes
.toBytes("-bad"), Bytes
.toBytes(".bad") };
205 for (byte[] illegalName
: illegalNames
) {
207 "Did not detect '" + Bytes
.toString(illegalName
) + "' as an illegal user table name",
208 IllegalArgumentException
.class, () -> TableName
.valueOf(illegalName
));
210 byte[] legalName
= Bytes
.toBytes("g-oo.d");
212 TableName
.valueOf(legalName
);
213 } catch (IllegalArgumentException e
) {
214 fail("Legal user table name: '" + Bytes
.toString(legalName
) +
215 "' caused IllegalArgumentException: " + e
.getMessage());
222 @Test (expected
=TableExistsException
.class)
223 public void testTableExistsExceptionWithATable() throws IOException
{
224 final TableName name
= TableName
.valueOf(this.name
.getMethodName());
225 TEST_UTIL
.createTable(name
, HConstants
.CATALOG_FAMILY
).close();
226 TEST_UTIL
.createTable(name
, HConstants
.CATALOG_FAMILY
);
230 * Can't disable a table if the table isn't in enabled state
232 @Test (expected
=TableNotEnabledException
.class)
233 public void testTableNotEnabledExceptionWithATable() throws IOException
{
234 final TableName name
= TableName
.valueOf(this.name
.getMethodName());
235 TEST_UTIL
.createTable(name
, HConstants
.CATALOG_FAMILY
).close();
236 ADMIN
.disableTable(name
);
237 ADMIN
.disableTable(name
);
241 * Can't enable a table if the table isn't in disabled state
243 @Test(expected
= TableNotDisabledException
.class)
244 public void testTableNotDisabledExceptionWithATable() throws IOException
{
245 final TableName name
= TableName
.valueOf(this.name
.getMethodName());
246 try (Table t
= TEST_UTIL
.createTable(name
, HConstants
.CATALOG_FAMILY
)) {
247 ADMIN
.enableTable(name
);
254 @Test(expected
= TableNotFoundException
.class)
255 public void testTableNotFoundExceptionWithoutAnyTables() throws IOException
{
256 TableName tableName
= TableName
.valueOf("testTableNotFoundExceptionWithoutAnyTables");
257 try (Table ht
= TEST_UTIL
.getConnection().getTable(tableName
)) {
258 ht
.get(new Get(Bytes
.toBytes("e")));
263 public void testShouldUnassignTheRegion() throws Exception
{
264 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
265 createTableWithDefaultConf(tableName
);
267 RegionInfo info
= null;
268 HRegionServer rs
= TEST_UTIL
.getRSForFirstRegionInTable(tableName
);
269 List
<RegionInfo
> onlineRegions
= ProtobufUtil
.getOnlineRegions(rs
.getRSRpcServices());
270 for (RegionInfo regionInfo
: onlineRegions
) {
271 if (!regionInfo
.getTable().isSystemTable()) {
273 ADMIN
.unassign(regionInfo
.getRegionName(), true);
276 boolean isInList
= ProtobufUtil
.getOnlineRegions(
277 rs
.getRSRpcServices()).contains(info
);
278 long timeout
= EnvironmentEdgeManager
.currentTime() + 10000;
279 while ((EnvironmentEdgeManager
.currentTime() < timeout
) && (isInList
)) {
281 isInList
= ProtobufUtil
.getOnlineRegions(
282 rs
.getRSRpcServices()).contains(info
);
285 assertFalse("The region should not be present in online regions list.",
290 public void testCloseRegionIfInvalidRegionNameIsPassed() throws Exception
{
291 final String name
= this.name
.getMethodName();
292 byte[] tableName
= Bytes
.toBytes(name
);
293 createTableWithDefaultConf(tableName
);
295 RegionInfo info
= null;
296 HRegionServer rs
= TEST_UTIL
.getRSForFirstRegionInTable(TableName
.valueOf(tableName
));
297 List
<RegionInfo
> onlineRegions
= ProtobufUtil
.getOnlineRegions(rs
.getRSRpcServices());
298 for (RegionInfo regionInfo
: onlineRegions
) {
299 if (!regionInfo
.isMetaRegion()) {
300 if (regionInfo
.getRegionNameAsString().contains(name
)) {
302 assertThrows(UnknownRegionException
.class,
303 () -> ADMIN
.unassign(Bytes
.toBytes(
304 "test,,1358563771069.acc1ad1b7962564fc3a43e5907e8db33."), true));
308 onlineRegions
= ProtobufUtil
.getOnlineRegions(rs
.getRSRpcServices());
309 assertTrue("The region should be present in online regions list.",
310 onlineRegions
.contains(info
));
314 public void testCloseRegionThatFetchesTheHRIFromMeta() throws Exception
{
315 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
316 createTableWithDefaultConf(tableName
);
318 RegionInfo info
= null;
319 HRegionServer rs
= TEST_UTIL
.getRSForFirstRegionInTable(tableName
);
320 List
<RegionInfo
> onlineRegions
= ProtobufUtil
.getOnlineRegions(rs
.getRSRpcServices());
321 for (RegionInfo regionInfo
: onlineRegions
) {
322 if (!regionInfo
.isMetaRegion()) {
323 if (regionInfo
.getRegionNameAsString().contains("TestHBACloseRegion2")) {
325 ADMIN
.unassign(regionInfo
.getRegionName(), true);
330 boolean isInList
= ProtobufUtil
.getOnlineRegions(
331 rs
.getRSRpcServices()).contains(info
);
332 long timeout
= EnvironmentEdgeManager
.currentTime() + 10000;
333 while ((EnvironmentEdgeManager
.currentTime() < timeout
) && (isInList
)) {
335 isInList
= ProtobufUtil
.getOnlineRegions(
336 rs
.getRSRpcServices()).contains(info
);
339 assertFalse("The region should not be present in online regions list.",
343 private Admin
createTable(TableName tableName
) throws IOException
{
344 Admin admin
= TEST_UTIL
.getAdmin();
346 TableDescriptorBuilder tableDescriptorBuilder
=
347 TableDescriptorBuilder
.newBuilder(tableName
);
348 ColumnFamilyDescriptor columnFamilyDescriptor
=
349 ColumnFamilyDescriptorBuilder
.newBuilder(Bytes
.toBytes("value")).build();
351 tableDescriptorBuilder
.setColumnFamily(columnFamilyDescriptor
);
352 admin
.createTable(tableDescriptorBuilder
.build());
356 private void createTableWithDefaultConf(byte[] TABLENAME
) throws IOException
{
357 createTableWithDefaultConf(TableName
.valueOf(TABLENAME
));
360 private void createTableWithDefaultConf(TableName TABLENAME
) throws IOException
{
361 TableDescriptorBuilder tableDescriptorBuilder
=
362 TableDescriptorBuilder
.newBuilder(TABLENAME
);
363 ColumnFamilyDescriptor columnFamilyDescriptor
=
364 ColumnFamilyDescriptorBuilder
.newBuilder(Bytes
.toBytes("value")).build();
365 tableDescriptorBuilder
.setColumnFamily(columnFamilyDescriptor
);
367 ADMIN
.createTable(tableDescriptorBuilder
.build());
374 public void testGetTableRegions() throws IOException
{
375 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
377 int expectedRegions
= 10;
379 // Use 80 bit numbers to make sure we aren't limited
380 byte [] startKey
= { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
381 byte [] endKey
= { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 };
384 TableDescriptor tableDescriptor
= TableDescriptorBuilder
.newBuilder(tableName
)
385 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(HConstants
.CATALOG_FAMILY
)).build();
386 ADMIN
.createTable(tableDescriptor
, startKey
, endKey
, expectedRegions
);
388 List
<RegionInfo
> RegionInfos
= ADMIN
.getRegions(tableName
);
390 assertEquals("Tried to create " + expectedRegions
+ " regions " +
391 "but only found " + RegionInfos
.size(),
392 expectedRegions
, RegionInfos
.size());
396 public void testMoveToPreviouslyAssignedRS() throws IOException
, InterruptedException
{
397 SingleProcessHBaseCluster cluster
= TEST_UTIL
.getHBaseCluster();
398 HMaster master
= cluster
.getMaster();
399 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
400 Admin localAdmin
= createTable(tableName
);
401 List
<RegionInfo
> tableRegions
= localAdmin
.getRegions(tableName
);
402 RegionInfo hri
= tableRegions
.get(0);
403 AssignmentManager am
= master
.getAssignmentManager();
404 ServerName server
= am
.getRegionStates().getRegionServerOfRegion(hri
);
405 localAdmin
.move(hri
.getEncodedNameAsBytes(), server
);
406 assertEquals("Current region server and region server before move should be same.", server
,
407 am
.getRegionStates().getRegionServerOfRegion(hri
));
411 public void testWALRollWriting() throws Exception
{
412 setUpforLogRolling();
413 String className
= this.getClass().getName();
414 StringBuilder v
= new StringBuilder(className
);
415 while (v
.length() < 1000) {
418 byte[] value
= Bytes
.toBytes(v
.toString());
419 HRegionServer regionServer
= startAndWriteData(TableName
.valueOf(name
.getMethodName()), value
);
420 LOG
.info("after writing there are "
421 + AbstractFSWALProvider
.getNumRolledLogFiles(regionServer
.getWAL(null)) + " log files");
424 for (HRegion r
: regionServer
.getOnlineRegionsLocalContext()) {
427 ADMIN
.rollWALWriter(regionServer
.getServerName());
428 int count
= AbstractFSWALProvider
.getNumRolledLogFiles(regionServer
.getWAL(null));
429 LOG
.info("after flushing all regions and rolling logs there are " +
430 count
+ " log files");
431 assertTrue(("actual count: " + count
), count
<= 2);
434 private void setUpforLogRolling() {
435 // Force a region split after every 768KB
436 TEST_UTIL
.getConfiguration().setLong(HConstants
.HREGION_MAX_FILESIZE
,
439 // We roll the log after every 32 writes
440 TEST_UTIL
.getConfiguration().setInt("hbase.regionserver.maxlogentries", 32);
442 TEST_UTIL
.getConfiguration().setInt(
443 "hbase.regionserver.logroll.errors.tolerated", 2);
444 TEST_UTIL
.getConfiguration().setInt("hbase.rpc.timeout", 10 * 1000);
446 // For less frequently updated regions flush after every 2 flushes
447 TEST_UTIL
.getConfiguration().setInt(
448 "hbase.hregion.memstore.optionalflushcount", 2);
450 // We flush the cache after every 8192 bytes
451 TEST_UTIL
.getConfiguration().setInt(HConstants
.HREGION_MEMSTORE_FLUSH_SIZE
,
454 // Increase the amount of time between client retries
455 TEST_UTIL
.getConfiguration().setLong("hbase.client.pause", 10 * 1000);
457 // Reduce thread wake frequency so that other threads can get
459 TEST_UTIL
.getConfiguration().setInt(HConstants
.THREAD_WAKE_FREQUENCY
,
462 /**** configuration for testLogRollOnDatanodeDeath ****/
463 // lower the namenode & datanode heartbeat so the namenode
464 // quickly detects datanode failures
465 TEST_UTIL
.getConfiguration().setInt("dfs.namenode.heartbeat.recheck-interval", 5000);
466 TEST_UTIL
.getConfiguration().setInt("dfs.heartbeat.interval", 1);
467 // the namenode might still try to choose the recently-dead datanode
468 // for a pipeline, so try to a new pipeline multiple times
469 TEST_UTIL
.getConfiguration().setInt("dfs.client.block.write.retries", 30);
470 TEST_UTIL
.getConfiguration().setInt(
471 "hbase.regionserver.hlog.tolerable.lowreplication", 2);
472 TEST_UTIL
.getConfiguration().setInt(
473 "hbase.regionserver.hlog.lowreplication.rolllimit", 3);
476 private HRegionServer
startAndWriteData(TableName tableName
, byte[] value
)
477 throws IOException
, InterruptedException
{
478 // When the hbase:meta table can be opened, the region servers are running
479 TEST_UTIL
.getConnection().getTable(TableName
.META_TABLE_NAME
).close();
481 // Create the test table and open it
482 TableDescriptor tableDescriptor
= TableDescriptorBuilder
.newBuilder(tableName
)
483 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(HConstants
.CATALOG_FAMILY
)).build();
484 ADMIN
.createTable(tableDescriptor
);
485 Table table
= TEST_UTIL
.getConnection().getTable(tableName
);
487 HRegionServer regionServer
= TEST_UTIL
.getRSForFirstRegionInTable(tableName
);
488 for (int i
= 1; i
<= 256; i
++) { // 256 writes should cause 8 log rolls
489 Put put
= new Put(Bytes
.toBytes("row" + String
.format("%1$04d", i
)));
490 put
.addColumn(HConstants
.CATALOG_FAMILY
, null, value
);
493 // After every 32 writes sleep to let the log roller run
496 } catch (InterruptedException e
) {
507 public void testDisableCatalogTable() throws Exception
{
509 ADMIN
.disableTable(TableName
.META_TABLE_NAME
);
510 fail("Expected to throw ConstraintException");
511 } catch (ConstraintException e
) {
513 // Before the fix for HBASE-6146, the below table creation was failing as the hbase:meta table
514 // actually getting disabled by the disableTable() call.
515 TableDescriptor tableDescriptor
=
516 TableDescriptorBuilder
.newBuilder(TableName
.valueOf(Bytes
.toBytes(name
.getMethodName())))
517 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(Bytes
.toBytes("cf1"))).build();
518 TEST_UTIL
.getAdmin().createTable(tableDescriptor
);
522 public void testIsEnabledOrDisabledOnUnknownTable() throws Exception
{
524 ADMIN
.isTableEnabled(TableName
.valueOf(name
.getMethodName()));
525 fail("Test should fail if isTableEnabled called on unknown table.");
526 } catch (IOException e
) {
530 ADMIN
.isTableDisabled(TableName
.valueOf(name
.getMethodName()));
531 fail("Test should fail if isTableDisabled called on unknown table.");
532 } catch (IOException e
) {
537 public void testBalancer() throws Exception
{
538 boolean initialState
= ADMIN
.isBalancerEnabled();
540 // Start the balancer, wait for it.
541 boolean prevState
= ADMIN
.balancerSwitch(!initialState
, true);
543 // The previous state should be the original state we observed
544 assertEquals(initialState
, prevState
);
546 // Current state should be opposite of the original
547 assertEquals(!initialState
, ADMIN
.isBalancerEnabled());
549 // Reset it back to what it was
550 prevState
= ADMIN
.balancerSwitch(initialState
, true);
552 // The previous state should be the opposite of the initial state
553 assertEquals(!initialState
, prevState
);
554 // Current state should be the original state again
555 assertEquals(initialState
, ADMIN
.isBalancerEnabled());
559 public void testRegionNormalizer() throws Exception
{
560 boolean initialState
= ADMIN
.isNormalizerEnabled();
563 boolean prevState
= ADMIN
.normalizerSwitch(!initialState
);
565 // The previous state should be the original state we observed
566 assertEquals(initialState
, prevState
);
568 // Current state should be opposite of the original
569 assertEquals(!initialState
, ADMIN
.isNormalizerEnabled());
571 // Reset it back to what it was
572 prevState
= ADMIN
.normalizerSwitch(initialState
);
574 // The previous state should be the opposite of the initial state
575 assertEquals(!initialState
, prevState
);
576 // Current state should be the original state again
577 assertEquals(initialState
, ADMIN
.isNormalizerEnabled());
581 public void testAbortProcedureFail() throws Exception
{
582 Random randomGenerator
= new Random();
583 long procId
= randomGenerator
.nextLong();
585 boolean abortResult
= ADMIN
.abortProcedure(procId
, true);
586 assertFalse(abortResult
);
590 public void testGetProcedures() throws Exception
{
591 String procList
= ADMIN
.getProcedures();
592 assertTrue(procList
.startsWith("["));
596 public void testGetLocks() throws Exception
{
597 String lockList
= ADMIN
.getLocks();
598 assertTrue(lockList
.startsWith("["));
602 public void testDecommissionRegionServers() throws Exception
{
603 List
<ServerName
> decommissionedRegionServers
= ADMIN
.listDecommissionedRegionServers();
604 assertTrue(decommissionedRegionServers
.isEmpty());
606 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
607 TEST_UTIL
.createMultiRegionTable(tableName
, Bytes
.toBytes("f"), 6);
609 ArrayList
<ServerName
> clusterRegionServers
=
610 new ArrayList
<>(ADMIN
.getClusterMetrics(EnumSet
.of(Option
.LIVE_SERVERS
))
611 .getLiveServerMetrics().keySet());
613 assertEquals(3, clusterRegionServers
.size());
615 HashMap
<ServerName
, List
<RegionInfo
>> serversToDecommssion
= new HashMap
<>();
616 // Get a server that has meta online. We will decommission two of the servers,
617 // leaving one online.
619 for (i
= 0; i
< clusterRegionServers
.size(); i
++) {
620 List
<RegionInfo
> regionsOnServer
= ADMIN
.getRegions(clusterRegionServers
.get(i
));
621 if (ADMIN
.getRegions(clusterRegionServers
.get(i
)).stream().anyMatch(p
-> p
.isMetaRegion())) {
622 serversToDecommssion
.put(clusterRegionServers
.get(i
), regionsOnServer
);
627 clusterRegionServers
.remove(i
);
628 // Get another server to decommission.
629 serversToDecommssion
.put(clusterRegionServers
.get(0),
630 ADMIN
.getRegions(clusterRegionServers
.get(0)));
632 ServerName remainingServer
= clusterRegionServers
.get(1);
635 ADMIN
.decommissionRegionServers(new ArrayList
<ServerName
>(serversToDecommssion
.keySet()), true);
636 assertEquals(2, ADMIN
.listDecommissionedRegionServers().size());
638 // Verify the regions have been off the decommissioned servers, all on the one
640 for (ServerName server
: serversToDecommssion
.keySet()) {
641 for (RegionInfo region
: serversToDecommssion
.get(server
)) {
642 TEST_UTIL
.assertRegionOnServer(region
, remainingServer
, 10000);
646 // Recommission and load the regions.
647 for (ServerName server
: serversToDecommssion
.keySet()) {
648 List
<byte[]> encodedRegionNames
= serversToDecommssion
.get(server
).stream()
649 .map(region
-> region
.getEncodedNameAsBytes()).collect(Collectors
.toList());
650 ADMIN
.recommissionRegionServer(server
, encodedRegionNames
);
652 assertTrue(ADMIN
.listDecommissionedRegionServers().isEmpty());
653 // Verify the regions have been moved to the recommissioned servers
654 for (ServerName server
: serversToDecommssion
.keySet()) {
655 for (RegionInfo region
: serversToDecommssion
.get(server
)) {
656 TEST_UTIL
.assertRegionOnServer(region
, server
, 10000);
662 * TestCase for HBASE-21355
665 public void testGetRegionInfo() throws Exception
{
666 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
667 Table table
= TEST_UTIL
.createTable(tableName
, Bytes
.toBytes("f"));
668 for (int i
= 0; i
< 100; i
++) {
669 table
.put(new Put(Bytes
.toBytes(i
)).addColumn(Bytes
.toBytes("f"), Bytes
.toBytes("q"),
672 ADMIN
.flush(tableName
);
674 HRegionServer rs
= TEST_UTIL
.getRSForFirstRegionInTable(table
.getName());
675 List
<HRegion
> regions
= rs
.getRegions(tableName
);
676 Assert
.assertEquals(1, regions
.size());
678 HRegion region
= regions
.get(0);
679 byte[] regionName
= region
.getRegionInfo().getRegionName();
680 HStore store
= region
.getStore(Bytes
.toBytes("f"));
681 long expectedStoreFilesSize
= store
.getStorefilesSize();
682 Assert
.assertNotNull(store
);
683 Assert
.assertEquals(expectedStoreFilesSize
, store
.getSize());
684 for (int i
= 0; i
< 10; i
++) {
685 RegionInfo ri
= ProtobufUtil
686 .toRegionInfo(TEST_UTIL
.getAsyncConnection().getRegionServerAdmin(rs
.getServerName())
687 .getRegionInfo(RequestConverter
.buildGetRegionInfoRequest(regionName
)).get()
690 Assert
.assertEquals(region
.getRegionInfo(), ri
);
692 // Make sure that the store size is still the actual file system's store size.
693 Assert
.assertEquals(expectedStoreFilesSize
, store
.getSize());
696 // Test querying using the encoded name only. When encoded name passed,
697 // and the target server is the Master, we return the full region name.
699 ServerName sn
= null;
700 try (Admin admin
= TEST_UTIL
.getConnection().getAdmin()) {
701 sn
= admin
.getMaster();
703 RegionInfo ri
= region
.getRegionInfo();
704 testGetWithRegionName(sn
, ri
, ri
.getEncodedNameAsBytes());
705 testGetWithRegionName(sn
, ri
, ri
.getRegionName());
706 // Try querying meta encoded name.
707 ri
= RegionInfoBuilder
.FIRST_META_REGIONINFO
;
708 testGetWithRegionName(sn
, ri
, ri
.getEncodedNameAsBytes());
709 testGetWithRegionName(sn
, ri
, ri
.getRegionName());
713 * Do get of RegionInfo from Master using encoded region name.
715 private void testGetWithRegionName(ServerName sn
, RegionInfo inputRI
,
716 byte [] regionName
) throws IOException
{
717 RegionInfo ri
= ProtobufUtil
.toRegionInfo(FutureUtils
.get(
718 TEST_UTIL
.getAsyncConnection().getRegionServerAdmin(sn
).getRegionInfo(
719 ProtobufUtil
.getGetRegionInfoRequest(regionName
))).getRegionInfo());
720 assertEquals(inputRI
, ri
);
724 public void testTableSplitFollowedByModify() throws Exception
{
725 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
726 TEST_UTIL
.createTable(tableName
, Bytes
.toBytes("f"));
728 // get the original table region count
729 List
<RegionInfo
> regions
= ADMIN
.getRegions(tableName
);
730 int originalCount
= regions
.size();
731 assertEquals(1, originalCount
);
733 // split the table and wait until region count increases
734 ADMIN
.split(tableName
, Bytes
.toBytes(3));
735 TEST_UTIL
.waitFor(30000, new Predicate
<Exception
>() {
738 public boolean evaluate() throws Exception
{
739 return ADMIN
.getRegions(tableName
).size() > originalCount
;
743 // do some table modification
744 TableDescriptor tableDesc
= TableDescriptorBuilder
.newBuilder(ADMIN
.getDescriptor(tableName
))
745 .setMaxFileSize(11111111)
747 ADMIN
.modifyTable(tableDesc
);
748 assertEquals(11111111, ADMIN
.getDescriptor(tableName
).getMaxFileSize());
752 public void testTableMergeFollowedByModify() throws Exception
{
753 final TableName tableName
= TableName
.valueOf(name
.getMethodName());
754 TEST_UTIL
.createTable(tableName
, new byte[][] { Bytes
.toBytes("f") },
755 new byte[][] { Bytes
.toBytes(3) });
757 // assert we have at least 2 regions in the table
758 List
<RegionInfo
> regions
= ADMIN
.getRegions(tableName
);
759 int originalCount
= regions
.size();
760 assertTrue(originalCount
>= 2);
762 byte[] nameOfRegionA
= regions
.get(0).getEncodedNameAsBytes();
763 byte[] nameOfRegionB
= regions
.get(1).getEncodedNameAsBytes();
765 // merge the table regions and wait until region count decreases
766 ADMIN
.mergeRegionsAsync(nameOfRegionA
, nameOfRegionB
, true);
767 TEST_UTIL
.waitFor(30000, new Predicate
<Exception
>() {
770 public boolean evaluate() throws Exception
{
771 return ADMIN
.getRegions(tableName
).size() < originalCount
;
775 // do some table modification
776 TableDescriptor tableDesc
= TableDescriptorBuilder
.newBuilder(ADMIN
.getDescriptor(tableName
))
777 .setMaxFileSize(11111111)
779 ADMIN
.modifyTable(tableDesc
);
780 assertEquals(11111111, ADMIN
.getDescriptor(tableName
).getMaxFileSize());
784 public void testSnapshotCleanupAsync() throws Exception
{
785 testSnapshotCleanup(false);
789 public void testSnapshotCleanupSync() throws Exception
{
790 testSnapshotCleanup(true);
793 private void testSnapshotCleanup(final boolean synchronous
) throws IOException
{
794 final boolean initialState
= ADMIN
.isSnapshotCleanupEnabled();
795 // Switch the snapshot auto cleanup state to opposite to initial state
796 boolean prevState
= ADMIN
.snapshotCleanupSwitch(!initialState
, synchronous
);
797 // The previous state should be the original state we observed
798 assertEquals(initialState
, prevState
);
799 // Current state should be opposite of the initial state
800 assertEquals(!initialState
, ADMIN
.isSnapshotCleanupEnabled());
801 // Reset the state back to what it was initially
802 prevState
= ADMIN
.snapshotCleanupSwitch(initialState
, synchronous
);
803 // The previous state should be the opposite of the initial state
804 assertEquals(!initialState
, prevState
);
805 // Current state should be the original state again
806 assertEquals(initialState
, ADMIN
.isSnapshotCleanupEnabled());
810 public void testSlowLogResponses() throws Exception
{
811 // get all live server names
812 Collection
<ServerName
> serverNames
= ADMIN
.getRegionServers();
813 List
<ServerName
> serverNameList
= new ArrayList
<>(serverNames
);
815 // clean up slowlog responses maintained in memory by RegionServers
816 List
<Boolean
> areSlowLogsCleared
= ADMIN
.clearSlowLogResponses(new HashSet
<>(serverNameList
));
818 int countFailedClearSlowResponse
= 0;
819 for (Boolean isSlowLogCleared
: areSlowLogsCleared
) {
820 if (!isSlowLogCleared
) {
821 ++countFailedClearSlowResponse
;
824 Assert
.assertEquals(countFailedClearSlowResponse
, 0);
826 List
<LogEntry
> onlineLogRecords
= ADMIN
.getLogEntries(new HashSet
<>(serverNames
),
827 "SLOW_LOG", ServerType
.REGION_SERVER
, 100, null);
828 // after cleanup of slowlog responses, total count of slowlog payloads should be 0
829 Assert
.assertEquals(onlineLogRecords
.size(), 0);
830 List
<LogEntry
> balancerDecisionRecords
=
831 ADMIN
.getLogEntries(null, "BALANCER_DECISION", ServerType
.MASTER
, 100, null);
832 Assert
.assertEquals(balancerDecisionRecords
.size(), 0);
836 public void testGetRegionServers() throws Exception
{
837 // get all live server names
838 List
<ServerName
> serverNames
= new ArrayList
<>(ADMIN
.getRegionServers(true));
839 Assert
.assertEquals(3, serverNames
.size());
841 List
<ServerName
> serversToDecom
= new ArrayList
<>();
842 ServerName serverToDecommission
= serverNames
.get(0);
844 serversToDecom
.add(serverToDecommission
);
845 ADMIN
.decommissionRegionServers(serversToDecom
, false);
846 waitForServerCommissioned(serverToDecommission
, true);
848 Assert
.assertEquals(2, ADMIN
.getRegionServers(true).size());
849 Assert
.assertEquals(3, ADMIN
.getRegionServers(false).size());
851 ADMIN
.recommissionRegionServer(serverToDecommission
, Collections
.emptyList());
852 waitForServerCommissioned(null, false);
854 Assert
.assertEquals(3, ADMIN
.getRegionServers(true).size());
855 Assert
.assertEquals(3, ADMIN
.getRegionServers(false).size());
858 private static void waitForServerCommissioned(ServerName excludeServer
,
859 boolean anyServerDecommissioned
) {
860 TEST_UTIL
.waitFor(3000, () -> {
862 List
<ServerName
> decomServers
= TEST_UTIL
.getAdmin().listDecommissionedRegionServers();
863 if (anyServerDecommissioned
) {
864 return decomServers
.size() == 1
865 && decomServers
.get(0).equals(excludeServer
);
867 return decomServers
.size() == 0;
869 } catch (IOException e
) {
870 throw new RuntimeException(e
);