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