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.assertTrue; 021 022import java.io.IOException; 023import java.util.ArrayList; 024import java.util.Collection; 025import java.util.HashMap; 026import java.util.Map; 027import org.apache.hadoop.conf.Configuration; 028import org.apache.hadoop.hbase.HBaseClassTestRule; 029import org.apache.hadoop.hbase.HBaseTestingUtility; 030import org.apache.hadoop.hbase.HConstants; 031import org.apache.hadoop.hbase.HTableDescriptor; 032import org.apache.hadoop.hbase.ServerName; 033import org.apache.hadoop.hbase.TableName; 034import org.apache.hadoop.hbase.client.RegionInfo; 035import org.apache.hadoop.hbase.client.Table; 036import org.apache.hadoop.hbase.testclassification.MediumTests; 037import org.apache.hadoop.hbase.testclassification.RegionServerTests; 038import org.apache.hadoop.hbase.util.Bytes; 039import org.apache.hadoop.hbase.util.RegionSplitter; 040import org.junit.AfterClass; 041import org.junit.BeforeClass; 042import org.junit.ClassRule; 043import org.junit.Test; 044import org.junit.experimental.categories.Category; 045import org.slf4j.Logger; 046import org.slf4j.LoggerFactory; 047 048@Category({ RegionServerTests.class, MediumTests.class }) 049public class TestRegionReplicasAreDistributed { 050 051 @ClassRule 052 public static final HBaseClassTestRule CLASS_RULE = 053 HBaseClassTestRule.forClass(TestRegionReplicasAreDistributed.class); 054 055 private static final Logger LOG = LoggerFactory.getLogger(TestRegionReplicasAreDistributed.class); 056 057 private static final int NB_SERVERS = 3; 058 private static Table table; 059 060 private static final HBaseTestingUtility HTU = new HBaseTestingUtility(); 061 private static final byte[] f = HConstants.CATALOG_FAMILY; 062 Map<ServerName, Collection<RegionInfo>> serverVsOnlineRegions; 063 Map<ServerName, Collection<RegionInfo>> serverVsOnlineRegions2; 064 Map<ServerName, Collection<RegionInfo>> serverVsOnlineRegions3; 065 Map<ServerName, Collection<RegionInfo>> serverVsOnlineRegions4; 066 067 @BeforeClass 068 public static void before() throws Exception { 069 HTU.getConfiguration().setInt("hbase.master.wait.on.regionservers.mintostart", 3); 070 071 HTU.startMiniCluster(NB_SERVERS); 072 Thread.sleep(3000); 073 final TableName tableName = 074 TableName.valueOf(TestRegionReplicasAreDistributed.class.getSimpleName()); 075 076 // Create table then get the single region for our new table. 077 createTableDirectlyFromHTD(tableName); 078 } 079 080 private static void createTableDirectlyFromHTD(final TableName tableName) throws IOException { 081 HTableDescriptor htd = new HTableDescriptor(tableName); 082 htd.setRegionReplication(3); 083 // create a table with 3 replication 084 085 table = HTU.createTable(htd, new byte[][] { f }, getSplits(20), 086 new Configuration(HTU.getConfiguration())); 087 } 088 089 private static byte[][] getSplits(int numRegions) { 090 RegionSplitter.UniformSplit split = new RegionSplitter.UniformSplit(); 091 split.setFirstRow(Bytes.toBytes(0L)); 092 split.setLastRow(Bytes.toBytes(Long.MAX_VALUE)); 093 return split.split(numRegions); 094 } 095 096 @AfterClass 097 public static void afterClass() throws Exception { 098 HRegionServer.TEST_SKIP_REPORTING_TRANSITION = false; 099 table.close(); 100 HTU.shutdownMiniCluster(); 101 } 102 103 private HRegionServer getRS() { 104 return HTU.getMiniHBaseCluster().getRegionServer(0); 105 } 106 107 private HRegionServer getSecondaryRS() { 108 return HTU.getMiniHBaseCluster().getRegionServer(1); 109 } 110 111 private HRegionServer getTertiaryRS() { 112 return HTU.getMiniHBaseCluster().getRegionServer(2); 113 } 114 115 @Test 116 public void testRegionReplicasCreatedAreDistributed() throws Exception { 117 try { 118 checkAndAssertRegionDistribution(false); 119 // now diesbale and enable the table again. It should be truly distributed 120 HTU.getAdmin().disableTable(table.getName()); 121 LOG.info("Disabled the table " + table.getName()); 122 LOG.info("enabling the table " + table.getName()); 123 HTU.getAdmin().enableTable(table.getName()); 124 LOG.info("Enabled the table " + table.getName()); 125 boolean res = checkAndAssertRegionDistribution(true); 126 assertTrue("Region retainment not done ", res); 127 } finally { 128 HTU.getAdmin().disableTable(table.getName()); 129 HTU.getAdmin().deleteTable(table.getName()); 130 } 131 } 132 133 private boolean checkAndAssertRegionDistribution(boolean checkfourth) throws Exception { 134 Collection<RegionInfo> onlineRegions = 135 new ArrayList<RegionInfo>(getRS().getOnlineRegionsLocalContext().size()); 136 for (HRegion region : getRS().getOnlineRegionsLocalContext()) { 137 onlineRegions.add(region.getRegionInfo()); 138 } 139 if (this.serverVsOnlineRegions == null) { 140 this.serverVsOnlineRegions = new HashMap<ServerName, Collection<RegionInfo>>(); 141 this.serverVsOnlineRegions.put(getRS().getServerName(), onlineRegions); 142 } else { 143 Collection<RegionInfo> existingRegions = 144 new ArrayList<RegionInfo>(this.serverVsOnlineRegions.get(getRS().getServerName())); 145 LOG.info("Count is " + existingRegions.size() + " " + onlineRegions.size()); 146 for (RegionInfo existingRegion : existingRegions) { 147 if (!onlineRegions.contains(existingRegion)) { 148 return false; 149 } 150 } 151 } 152 Collection<RegionInfo> onlineRegions2 = 153 new ArrayList<RegionInfo>(getSecondaryRS().getOnlineRegionsLocalContext().size()); 154 for (HRegion region : getSecondaryRS().getOnlineRegionsLocalContext()) { 155 onlineRegions2.add(region.getRegionInfo()); 156 } 157 if (this.serverVsOnlineRegions2 == null) { 158 this.serverVsOnlineRegions2 = new HashMap<ServerName, Collection<RegionInfo>>(); 159 this.serverVsOnlineRegions2.put(getSecondaryRS().getServerName(), onlineRegions2); 160 } else { 161 Collection<RegionInfo> existingRegions = new ArrayList<RegionInfo>( 162 this.serverVsOnlineRegions2.get(getSecondaryRS().getServerName())); 163 LOG.info("Count is " + existingRegions.size() + " " + onlineRegions2.size()); 164 for (RegionInfo existingRegion : existingRegions) { 165 if (!onlineRegions2.contains(existingRegion)) { 166 return false; 167 } 168 } 169 } 170 Collection<RegionInfo> onlineRegions3 = 171 new ArrayList<RegionInfo>(getTertiaryRS().getOnlineRegionsLocalContext().size()); 172 for (HRegion region : getTertiaryRS().getOnlineRegionsLocalContext()) { 173 onlineRegions3.add(region.getRegionInfo()); 174 } 175 if (this.serverVsOnlineRegions3 == null) { 176 this.serverVsOnlineRegions3 = new HashMap<ServerName, Collection<RegionInfo>>(); 177 this.serverVsOnlineRegions3.put(getTertiaryRS().getServerName(), onlineRegions3); 178 } else { 179 Collection<RegionInfo> existingRegions = 180 new ArrayList<RegionInfo>(this.serverVsOnlineRegions3.get(getTertiaryRS().getServerName())); 181 LOG.info("Count is " + existingRegions.size() + " " + onlineRegions3.size()); 182 for (RegionInfo existingRegion : existingRegions) { 183 if (!onlineRegions3.contains(existingRegion)) { 184 return false; 185 } 186 } 187 } 188 // META and namespace to be added 189 return true; 190 } 191}