001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver; 019 020import static org.junit.jupiter.api.Assertions.assertTrue; 021import static org.junit.jupiter.api.Assertions.fail; 022 023import java.io.IOException; 024import java.util.List; 025import java.util.stream.Collectors; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.hbase.DoNotRetryIOException; 028import org.apache.hadoop.hbase.HBaseTestingUtil; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.client.Admin; 031import org.apache.hadoop.hbase.client.DoNotRetryRegionException; 032import org.apache.hadoop.hbase.client.Put; 033import org.apache.hadoop.hbase.client.RegionInfo; 034import org.apache.hadoop.hbase.client.Table; 035import org.apache.hadoop.hbase.testclassification.MediumTests; 036import org.apache.hadoop.hbase.util.Bytes; 037import org.junit.jupiter.api.AfterAll; 038import org.junit.jupiter.api.BeforeAll; 039import org.junit.jupiter.api.BeforeEach; 040import org.junit.jupiter.api.Tag; 041import org.junit.jupiter.api.Test; 042import org.junit.jupiter.api.TestInfo; 043 044/** 045 * Test move fails when table disabled 046 */ 047@Tag(MediumTests.TAG) 048public class TestRegionMove { 049 050 private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 051 public static Configuration CONF; 052 protected static final String F1 = "f1"; 053 054 // Test names 055 protected TableName tableName; 056 protected String method; 057 058 @BeforeAll 059 public static void startCluster() throws Exception { 060 TEST_UTIL.startMiniCluster(2); 061 } 062 063 @AfterAll 064 public static void stopCluster() throws Exception { 065 TEST_UTIL.shutdownMiniCluster(); 066 } 067 068 @BeforeEach 069 public void setup(TestInfo testInfo) throws IOException { 070 CONF = TEST_UTIL.getConfiguration(); 071 method = testInfo.getTestMethod().get().getName(); 072 tableName = TableName.valueOf(method); 073 } 074 075 @Test 076 public void testDisableAndMove() throws Exception { 077 Admin admin = TEST_UTIL.getAdmin(); 078 079 // Create a table with more than one region 080 Table t = TEST_UTIL.createMultiRegionTable(tableName, Bytes.toBytes(F1), 10); 081 TEST_UTIL.waitUntilAllRegionsAssigned(tableName); 082 083 // Write an update to each region 084 for (RegionInfo regionInfo : admin.getRegions(tableName)) { 085 byte[] startKey = regionInfo.getStartKey(); 086 // The startKey of the first region is "empty", which would throw an error if we try to 087 // Put that. 088 byte[] rowKey = org.apache.hbase.thirdparty.com.google.common.primitives.Bytes 089 .concat(startKey, Bytes.toBytes("1")); 090 Put p = new Put(rowKey); 091 p.addColumn(Bytes.toBytes(F1), Bytes.toBytes("q1"), Bytes.toBytes("value")); 092 t.put(p); 093 } 094 095 // Get a Region which is on the first RS 096 HRegionServer rs1 = TEST_UTIL.getRSForFirstRegionInTable(tableName); 097 HRegionServer rs2 = TEST_UTIL.getOtherRegionServer(rs1); 098 List<RegionInfo> regionsOnRS1ForTable = admin.getRegions(rs1.getServerName()).stream() 099 .filter((regionInfo) -> regionInfo.getTable().equals(tableName)).collect(Collectors.toList()); 100 assertTrue(!regionsOnRS1ForTable.isEmpty(), "Expected to find at least one region for " 101 + tableName + " on " + rs1.getServerName() + ", but found none"); 102 final RegionInfo regionToMove = regionsOnRS1ForTable.get(0); 103 104 // Offline the region and then try to move it. Should fail. 105 admin.unassign(regionToMove.getRegionName(), true); 106 try { 107 admin.move(regionToMove.getEncodedNameAsBytes(), rs2.getServerName()); 108 fail(); 109 } catch (DoNotRetryRegionException e) { 110 // We got expected exception 111 } 112 // Reassign for next stage of test. 113 admin.assign(regionToMove.getRegionName()); 114 115 // Disable the table 116 admin.disableTable(tableName); 117 118 try { 119 // Move the region to the other RS -- should fail 120 admin.move(regionToMove.getEncodedNameAsBytes(), rs2.getServerName()); 121 fail(); 122 } catch (DoNotRetryIOException e) { 123 // We got expected exception 124 } 125 } 126}