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