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.assertEquals; 021import static org.junit.jupiter.api.Assertions.assertFalse; 022import static org.junit.jupiter.api.Assertions.assertTrue; 023 024import java.io.IOException; 025import java.util.ArrayList; 026import java.util.List; 027import org.apache.hadoop.hbase.HBaseTestingUtil; 028import org.apache.hadoop.hbase.SingleProcessHBaseCluster; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.client.Admin; 031import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 032import org.apache.hadoop.hbase.client.Put; 033import org.apache.hadoop.hbase.client.RegionInfo; 034import org.apache.hadoop.hbase.client.RegionLocator; 035import org.apache.hadoop.hbase.client.Result; 036import org.apache.hadoop.hbase.client.ResultScanner; 037import org.apache.hadoop.hbase.client.Scan; 038import org.apache.hadoop.hbase.client.Table; 039import org.apache.hadoop.hbase.client.TableDescriptor; 040import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 041import org.apache.hadoop.hbase.master.HMaster; 042import org.apache.hadoop.hbase.testclassification.MediumTests; 043import org.apache.hadoop.hbase.testclassification.RegionServerTests; 044import org.apache.hadoop.hbase.util.Bytes; 045import org.junit.jupiter.api.BeforeEach; 046import org.junit.jupiter.api.Tag; 047import org.junit.jupiter.api.Test; 048import org.junit.jupiter.api.TestInfo; 049import org.slf4j.Logger; 050import org.slf4j.LoggerFactory; 051 052/** 053 * Tests that need to spin up a cluster testing an {@link HRegion}. Use {@link TestHRegion} if you 054 * don't need a cluster, if you can test w/ a standalone {@link HRegion}. 055 */ 056@Tag(RegionServerTests.TAG) 057@Tag(MediumTests.TAG) 058public class TestHRegionOnCluster { 059 060 private static final Logger LOG = LoggerFactory.getLogger(TestHRegionOnCluster.class); 061 private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 062 private String name; 063 064 @BeforeEach 065 public void setTestName(TestInfo testInfo) { 066 this.name = testInfo.getTestMethod().get().getName(); 067 } 068 069 @Test 070 public void testDataCorrectnessReplayingRecoveredEdits() throws Exception { 071 final int NUM_RS = 3; 072 Admin hbaseAdmin = null; 073 TEST_UTIL.startMiniCluster(NUM_RS); 074 075 try { 076 final TableName tableName = TableName.valueOf(name); 077 final byte[] FAMILY = Bytes.toBytes("family"); 078 SingleProcessHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 079 HMaster master = cluster.getMaster(); 080 081 // Create table 082 TableDescriptor tableDescriptor = TableDescriptorBuilder.newBuilder(tableName) 083 .setColumnFamily(ColumnFamilyDescriptorBuilder.of(FAMILY)).build(); 084 hbaseAdmin = master.getConnection().getAdmin(); 085 hbaseAdmin.createTable(tableDescriptor); 086 087 assertTrue(hbaseAdmin.isTableAvailable(tableName)); 088 089 // Put data: r1->v1 090 LOG.info("Loading r1 to v1 into " + tableName); 091 Table table = TEST_UTIL.getConnection().getTable(tableName); 092 putDataAndVerify(table, "r1", FAMILY, "v1", 1); 093 094 TEST_UTIL.waitUntilAllRegionsAssigned(table.getName()); 095 // Move region to target server 096 097 RegionInfo regionInfo; 098 try (RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(tableName)) { 099 regionInfo = locator.getRegionLocation(Bytes.toBytes("r1")).getRegion(); 100 } 101 102 int originServerNum = cluster.getServerWith(regionInfo.getRegionName()); 103 HRegionServer originServer = cluster.getRegionServer(originServerNum); 104 int targetServerNum = (originServerNum + 1) % NUM_RS; 105 HRegionServer targetServer = cluster.getRegionServer(targetServerNum); 106 assertFalse(originServer.equals(targetServer)); 107 108 TEST_UTIL.waitUntilAllRegionsAssigned(table.getName()); 109 LOG.info("Moving " + regionInfo.getEncodedName() + " to " + targetServer.getServerName()); 110 hbaseAdmin.move(regionInfo.getEncodedNameAsBytes(), targetServer.getServerName()); 111 do { 112 Thread.sleep(1); 113 } while (cluster.getServerWith(regionInfo.getRegionName()) == originServerNum); 114 115 // Put data: r2->v2 116 LOG.info("Loading r2 to v2 into " + tableName); 117 putDataAndVerify(table, "r2", FAMILY, "v2", 2); 118 119 TEST_UTIL.waitUntilAllRegionsAssigned(table.getName()); 120 // Move region to origin server 121 LOG.info("Moving " + regionInfo.getEncodedName() + " to " + originServer.getServerName()); 122 hbaseAdmin.move(regionInfo.getEncodedNameAsBytes(), originServer.getServerName()); 123 do { 124 Thread.sleep(1); 125 } while (cluster.getServerWith(regionInfo.getRegionName()) == targetServerNum); 126 127 // Put data: r3->v3 128 LOG.info("Loading r3 to v3 into " + tableName); 129 putDataAndVerify(table, "r3", FAMILY, "v3", 3); 130 131 // Kill target server 132 LOG.info("Killing target server " + targetServer.getServerName()); 133 targetServer.kill(); 134 cluster.getRegionServerThreads().get(targetServerNum).join(); 135 // Wait until finish processing of shutdown 136 while (master.getServerManager().areDeadServersInProgress()) { 137 Thread.sleep(5); 138 } 139 // Kill origin server 140 LOG.info("Killing origin server " + targetServer.getServerName()); 141 originServer.kill(); 142 cluster.getRegionServerThreads().get(originServerNum).join(); 143 144 // Put data: r4->v4 145 LOG.info("Loading r4 to v4 into " + tableName); 146 putDataAndVerify(table, "r4", FAMILY, "v4", 4); 147 148 } finally { 149 if (hbaseAdmin != null) hbaseAdmin.close(); 150 TEST_UTIL.shutdownMiniCluster(); 151 } 152 } 153 154 private void putDataAndVerify(Table table, String row, byte[] family, String value, int verifyNum) 155 throws IOException { 156 System.out.println("=========Putting data :" + row); 157 Put put = new Put(Bytes.toBytes(row)); 158 put.addColumn(family, Bytes.toBytes("q1"), Bytes.toBytes(value)); 159 table.put(put); 160 ResultScanner resultScanner = table.getScanner(new Scan()); 161 List<Result> results = new ArrayList<>(); 162 while (true) { 163 Result r = resultScanner.next(); 164 if (r == null) break; 165 results.add(r); 166 } 167 resultScanner.close(); 168 if (results.size() != verifyNum) { 169 System.out.println(results); 170 } 171 assertEquals(verifyNum, results.size()); 172 } 173 174}