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