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