001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.hbase.util;
020
021import org.apache.hadoop.hbase.HBaseClassTestRule;
022import org.apache.hadoop.hbase.HBaseTestingUtility;
023import org.apache.hadoop.hbase.MiniHBaseCluster;
024import org.apache.hadoop.hbase.TableName;
025import org.apache.hadoop.hbase.client.Admin;
026import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
027import org.apache.hadoop.hbase.client.Put;
028import org.apache.hadoop.hbase.client.Table;
029import org.apache.hadoop.hbase.client.TableDescriptor;
030import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
031import org.apache.hadoop.hbase.regionserver.HRegion;
032import org.apache.hadoop.hbase.regionserver.HRegionServer;
033import org.apache.hadoop.hbase.testclassification.LargeTests;
034import org.apache.hadoop.hbase.testclassification.MiscTests;
035import org.junit.After;
036import org.junit.AfterClass;
037import org.junit.Assert;
038import org.junit.Before;
039import org.junit.BeforeClass;
040import org.junit.ClassRule;
041import org.junit.Rule;
042import org.junit.Test;
043import org.junit.experimental.categories.Category;
044import org.junit.rules.TestName;
045import org.slf4j.Logger;
046import org.slf4j.LoggerFactory;
047import java.util.ArrayList;
048import java.util.List;
049import java.util.concurrent.TimeUnit;
050import java.util.stream.Collectors;
051
052/**
053 * Tests for Region Mover Load/Unload functionality with and without ack mode and also to test
054 * exclude functionality useful for rack decommissioning
055 */
056@Category({ MiscTests.class, LargeTests.class})
057public class TestRegionMover2 {
058
059  @ClassRule
060  public static final HBaseClassTestRule CLASS_RULE =
061    HBaseClassTestRule.forClass(TestRegionMover2.class);
062
063  @Rule
064  public TestName name = new TestName();
065
066  private static final Logger LOG = LoggerFactory.getLogger(TestRegionMover2.class);
067
068  private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
069
070  @BeforeClass
071  public static void setUpBeforeClass() throws Exception {
072    TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 4);
073    TEST_UTIL.startMiniCluster(3);
074    TEST_UTIL.getAdmin().balancerSwitch(false, true);
075  }
076
077  @AfterClass
078  public static void tearDownAfterClass() throws Exception {
079    TEST_UTIL.shutdownMiniCluster();
080  }
081
082  @Before
083  public void setUp() throws Exception {
084    final TableName tableName = TableName.valueOf(name.getMethodName());
085    TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(tableName)
086      .setColumnFamily(ColumnFamilyDescriptorBuilder.of("fam1")).build();
087    int startKey = 0;
088    int endKey = 80000;
089    TEST_UTIL.getAdmin().createTable(tableDesc, Bytes.toBytes(startKey), Bytes.toBytes(endKey), 9);
090  }
091
092  @After
093  public void tearDown() throws Exception {
094    final TableName tableName = TableName.valueOf(name.getMethodName());
095    TEST_UTIL.getAdmin().disableTable(tableName);
096    TEST_UTIL.getAdmin().deleteTable(tableName);
097  }
098
099  @Test
100  public void testWithSplitRegions() throws Exception {
101    final TableName tableName = TableName.valueOf(name.getMethodName());
102    MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
103    Admin admin = TEST_UTIL.getAdmin();
104    Table table = TEST_UTIL.getConnection().getTable(tableName);
105    List<Put> puts = new ArrayList<>();
106    for (int i = 10; i < 50000; i++) {
107      puts.add(new Put(Bytes.toBytes(i))
108        .addColumn(Bytes.toBytes("fam1"), Bytes.toBytes("q1"), Bytes.toBytes("val_" + i)));
109    }
110    table.put(puts);
111    admin.flush(tableName);
112    admin.compact(tableName);
113    HRegionServer regionServer = cluster.getRegionServer(0);
114    String rsName = regionServer.getServerName().getAddress().toString();
115    int numRegions = regionServer.getNumberOfOnlineRegions();
116    List<HRegion> hRegions = regionServer.getRegions().stream()
117      .filter(hRegion -> hRegion.getRegionInfo().getTable().equals(tableName))
118      .collect(Collectors.toList());
119
120    RegionMover.RegionMoverBuilder rmBuilder =
121      new RegionMover.RegionMoverBuilder(rsName, TEST_UTIL.getConfiguration()).ack(true)
122        .maxthreads(8);
123    try (RegionMover rm = rmBuilder.build()) {
124      LOG.debug("Unloading {}", regionServer.getServerName());
125      rm.unload();
126      Assert.assertEquals(0, regionServer.getNumberOfOnlineRegions());
127      LOG.debug("Successfully Unloaded, now Loading");
128      HRegion hRegion = hRegions.get(1);
129      if (hRegion.getRegionInfo().getStartKey().length == 0) {
130        hRegion = hRegions.get(0);
131      }
132      int startKey = 0;
133      int endKey = Integer.MAX_VALUE;
134      if (hRegion.getRegionInfo().getStartKey().length > 0) {
135        startKey = Bytes.toInt(hRegion.getRegionInfo().getStartKey());
136      }
137      if (hRegion.getRegionInfo().getEndKey().length > 0) {
138        endKey = Bytes.toInt(hRegion.getRegionInfo().getEndKey());
139      }
140      int midKey = startKey + (endKey - startKey) / 2;
141      admin.splitRegionAsync(hRegion.getRegionInfo().getRegionName(), Bytes.toBytes(midKey))
142        .get(5, TimeUnit.SECONDS);
143      Assert.assertTrue(rm.load());
144      Assert.assertEquals(numRegions - 1, regionServer.getNumberOfOnlineRegions());
145    }
146  }
147
148  @Test
149  public void testFailedRegionMove() throws Exception {
150    final TableName tableName = TableName.valueOf(name.getMethodName());
151    MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
152    Admin admin = TEST_UTIL.getAdmin();
153    Table table = TEST_UTIL.getConnection().getTable(tableName);
154    List<Put> puts = new ArrayList<>();
155    for (int i = 0; i < 1000; i++) {
156      puts.add(new Put(Bytes.toBytes("rowkey_" + i))
157        .addColumn(Bytes.toBytes("fam1"), Bytes.toBytes("q1"), Bytes.toBytes("val_" + i)));
158    }
159    table.put(puts);
160    admin.flush(tableName);
161    HRegionServer regionServer = cluster.getRegionServer(0);
162    String rsName = regionServer.getServerName().getAddress().toString();
163    List<HRegion> hRegions = regionServer.getRegions().stream()
164      .filter(hRegion -> hRegion.getRegionInfo().getTable().equals(tableName))
165      .collect(Collectors.toList());
166    RegionMover.RegionMoverBuilder rmBuilder =
167      new RegionMover.RegionMoverBuilder(rsName, TEST_UTIL.getConfiguration()).ack(true)
168        .maxthreads(8);
169    try (RegionMover rm = rmBuilder.build()) {
170      LOG.debug("Unloading {}", regionServer.getServerName());
171      rm.unload();
172      Assert.assertEquals(0, regionServer.getNumberOfOnlineRegions());
173      LOG.debug("Successfully Unloaded, now Loading");
174      admin.offline(hRegions.get(0).getRegionInfo().getRegionName());
175      // loading regions will fail because of offline region
176      Assert.assertFalse(rm.load());
177    }
178  }
179
180}