HBASE-24033 Add ut for loading the corrupt recovered hfiles (#1322)
[hbase.git] / hbase-server / src / test / java / org / apache / hadoop / hbase / client / TestAdmin2.java
blob558af1891488cce3947ce1cf05691c2f8b9205f0
1 /**
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;
69 /**
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 {
77 @ClassRule
78 public static final HBaseClassTestRule CLASS_RULE =
79 HBaseClassTestRule.forClass(TestAdmin2.class);
81 private static final Logger LOG = LoggerFactory.getLogger(TestAdmin2.class);
83 @Test
84 public void testCreateBadTables() throws IOException {
85 String msg = null;
86 try {
87 ADMIN.createTable(new HTableDescriptor(TableName.META_TABLE_NAME));
88 } catch(TableExistsException e) {
89 msg = e.toString();
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);
103 int count = 10;
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)) {
110 @Override
111 public void run() {
112 try {
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++) {
124 threads[i].start();
126 for (int i = 0; i < count; i++) {
127 while(threads[i].isAlive()) {
128 try {
129 Thread.sleep(100);
130 } catch (InterruptedException e) {
131 // continue
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'.
143 * @throws Exception
145 @Test
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();
165 /***
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
169 * issue anymore
171 @Test
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);
177 try {
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);
189 } finally {
190 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, oldTimeout);
195 * Test read only tables
196 * @throws Exception
198 @Test
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);
206 table.put(put);
207 table.close();
211 * Test that user table names can contain '-' and '.' so long as they do not
212 * start with same. HBASE-771
214 @Test
215 public void testTableNames() throws IOException {
216 byte[][] illegalNames = new byte[][] {
217 Bytes.toBytes("-bad"),
218 Bytes.toBytes(".bad")
220 for (byte[] illegalName : illegalNames) {
221 try {
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) {
226 // expected
229 byte[] legalName = Bytes.toBytes("g-oo.d");
230 try {
231 new HTableDescriptor(TableName.valueOf(legalName));
232 } catch (IllegalArgumentException e) {
233 throw new IOException("Legal user table name: '" +
234 Bytes.toString(legalName) + "' caused IllegalArgumentException: " +
235 e.getMessage());
240 * For HADOOP-2579
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);
272 * For HADOOP-2579
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")));
282 @Test
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()) {
292 info = regionInfo;
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)) {
300 Thread.sleep(100);
301 isInList = ProtobufUtil.getOnlineRegions(
302 rs.getRSRpcServices()).contains(info);
305 assertFalse("The region should not be present in online regions list.",
306 isInList);
309 @Test
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)) {
321 info = regionInfo;
322 try {
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));
335 @Test
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")) {
346 info = regionInfo;
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)) {
356 Thread.sleep(100);
357 isInList = ProtobufUtil.getOnlineRegions(
358 rs.getRSRpcServices()).contains(info);
361 assertFalse("The region should not be present in online regions list.",
362 isInList);
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());
375 return admin;
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());
393 * For HBASE-2556
395 @Test
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());
420 @Test
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));
435 @Test
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) {
441 v.append(className);
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");
448 // flush all regions
449 for (HRegion r : regionServer.getOnlineRegionsLocalContext()) {
450 r.flush(true);
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,
462 768L * 1024L);
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,
477 8192);
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
483 // a chance to run.
484 TEST_UTIL.getConfiguration().setInt(HConstants.THREAD_WAKE_FREQUENCY,
485 2 * 1000);
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);
519 table.put(put);
520 if (i % 32 == 0) {
521 // After every 32 writes sleep to let the log roller run
522 try {
523 Thread.sleep(2000);
524 } catch (InterruptedException e) {
525 // continue
530 table.close();
531 return regionServer;
534 @Test
535 public void testDisableCatalogTable() throws Exception {
536 try {
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);
554 @Test
555 public void testIsEnabledOrDisabledOnUnknownTable() throws Exception {
556 try {
557 ADMIN.isTableEnabled(TableName.valueOf(name.getMethodName()));
558 fail("Test should fail if isTableEnabled called on unknown table.");
559 } catch (IOException e) {
562 try {
563 ADMIN.isTableDisabled(TableName.valueOf(name.getMethodName()));
564 fail("Test should fail if isTableDisabled called on unknown table.");
565 } catch (IOException e) {
569 @Test
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());
591 @Test
592 public void testRegionNormalizer() throws Exception {
593 boolean initialState = ADMIN.isNormalizerEnabled();
595 // flip state
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());
613 @Test
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);
622 @Test
623 public void testGetProcedures() throws Exception {
624 String procList = ADMIN.getProcedures();
625 assertTrue(procList.startsWith("["));
628 @Test
629 public void testGetLocks() throws Exception {
630 String lockList = ADMIN.getLocks();
631 assertTrue(lockList.startsWith("["));
634 @Test
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.
651 int i;
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);
656 break;
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);
667 // Decommission
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
672 // remaining server.
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
697 @Test
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"),
703 Bytes.toBytes(i)));
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()
721 .getRegionInfo());
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.
731 // Convenience.
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);
756 @Test
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>() {
770 @Override
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)
779 .build();
780 ADMIN.modifyTable(tableDesc);
781 assertEquals(11111111, ADMIN.getDescriptor(tableName).getMaxFileSize());
784 @Test
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>() {
802 @Override
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)
811 .build();
812 ADMIN.modifyTable(tableDesc);
813 assertEquals(11111111, ADMIN.getDescriptor(tableName).getMaxFileSize());
816 @Test
817 public void testSnapshotCleanupAsync() throws Exception {
818 testSnapshotCleanup(false);
821 @Test
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());
842 @Test
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),
861 slowLogQueryFilter);
863 // after cleanup of slowlog responses, total count of slowlog payloads should be 0
864 Assert.assertEquals(slowLogRecords.size(), 0);