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.util; 019 020import static org.junit.Assert.assertEquals; 021 022import java.io.File; 023import java.io.FileWriter; 024import org.apache.hadoop.conf.Configuration; 025import org.apache.hadoop.hbase.HBaseClassTestRule; 026import org.apache.hadoop.hbase.HBaseTestingUtility; 027import org.apache.hadoop.hbase.HColumnDescriptor; 028import org.apache.hadoop.hbase.HConstants; 029import org.apache.hadoop.hbase.HTableDescriptor; 030import org.apache.hadoop.hbase.MiniHBaseCluster; 031import org.apache.hadoop.hbase.TableName; 032import org.apache.hadoop.hbase.Waiter.Predicate; 033import org.apache.hadoop.hbase.client.Admin; 034import org.apache.hadoop.hbase.regionserver.HRegionServer; 035import org.apache.hadoop.hbase.testclassification.MediumTests; 036import org.apache.hadoop.hbase.util.RegionMover.RegionMoverBuilder; 037import org.junit.AfterClass; 038import org.junit.Before; 039import org.junit.BeforeClass; 040import org.junit.ClassRule; 041import org.junit.Test; 042import org.junit.experimental.categories.Category; 043import org.slf4j.Logger; 044import org.slf4j.LoggerFactory; 045 046 047/** 048 * Tests for Region Mover Load/Unload functionality with and without ack mode and also to test 049 * exclude functionality useful for rack decommissioning 050 */ 051@Category(MediumTests.class) 052public class TestRegionMover { 053 054 @ClassRule 055 public static final HBaseClassTestRule CLASS_RULE = 056 HBaseClassTestRule.forClass(TestRegionMover.class); 057 058 final Logger LOG = LoggerFactory.getLogger(getClass()); 059 protected final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 060 061 @BeforeClass 062 public static void setUpBeforeClass() throws Exception { 063 TEST_UTIL.startMiniCluster(3); 064 } 065 066 @AfterClass 067 public static void tearDownAfterClass() throws Exception { 068 TEST_UTIL.shutdownMiniCluster(); 069 } 070 071 @Before 072 public void setUp() throws Exception { 073 // Create a pre-split table just to populate some regions 074 TableName tableName = TableName.valueOf("testRegionMover"); 075 Admin admin = TEST_UTIL.getAdmin(); 076 if (admin.tableExists(tableName)) { 077 TEST_UTIL.deleteTable(tableName); 078 } 079 HTableDescriptor tableDesc = new HTableDescriptor(tableName); 080 HColumnDescriptor fam1 = new HColumnDescriptor("fam1"); 081 tableDesc.addFamily(fam1); 082 083 try { 084 admin.setBalancerRunning(false, true); 085 String startKey = "a"; 086 String endKey = "z"; 087 admin.createTable(tableDesc, startKey.getBytes(), endKey.getBytes(), 9); 088 } finally { 089 if (admin != null) { 090 admin.close(); 091 } 092 } 093 } 094 095 @Test 096 public void testLoadWithAck() throws Exception { 097 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 098 HRegionServer regionServer = cluster.getRegionServer(0); 099 String rsName = regionServer.getServerName().getHostname(); 100 int port = regionServer.getServerName().getPort(); 101 int noRegions = regionServer.getNumberOfOnlineRegions(); 102 String rs = rsName + ":" + Integer.toString(port); 103 RegionMoverBuilder rmBuilder = new RegionMoverBuilder(rs, TEST_UTIL.getConfiguration()) 104 .ack(true).maxthreads(8); 105 RegionMover rm = rmBuilder.build(); 106 LOG.info("Unloading " + rs); 107 rm.unload(); 108 assertEquals(0, regionServer.getNumberOfOnlineRegions()); 109 LOG.info("Successfully Unloaded\nNow Loading"); 110 rm.load(); 111 assertEquals(noRegions, regionServer.getNumberOfOnlineRegions()); 112 } 113 114 /** Test to unload a regionserver first and then load it using no Ack mode 115 * we check if some regions are loaded on the region server(since no ack is best effort) 116 */ 117 @Test 118 public void testLoadWithoutAck() throws Exception { 119 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 120 final HRegionServer regionServer = cluster.getRegionServer(0); 121 String rsName = regionServer.getServerName().getHostname(); 122 int port = regionServer.getServerName().getPort(); 123 int noRegions = regionServer.getNumberOfOnlineRegions(); 124 String rs = rsName + ":" + Integer.toString(port); 125 RegionMoverBuilder rmBuilder = new RegionMoverBuilder(rs, TEST_UTIL.getConfiguration()) 126 .ack(true); 127 RegionMover rm = rmBuilder.build(); 128 LOG.info("Unloading " + rs); 129 rm.unload(); 130 assertEquals(0, regionServer.getNumberOfOnlineRegions()); 131 LOG.info("Successfully Unloaded\nNow Loading"); 132 rm = rmBuilder.ack(false).build(); 133 rm.load(); 134 TEST_UTIL.waitFor(5000, 500, new Predicate<Exception>() { 135 @Override 136 public boolean evaluate() throws Exception { 137 return regionServer.getNumberOfOnlineRegions() > 0; 138 } 139 }); 140 } 141 142 @Test 143 public void testUnloadWithoutAck() throws Exception { 144 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 145 final HRegionServer regionServer = cluster.getRegionServer(0); 146 final int noRegions = regionServer.getNumberOfOnlineRegions(); 147 String rsName = regionServer.getServerName().getHostname(); 148 int port = regionServer.getServerName().getPort(); 149 String rs = rsName + ":" + Integer.toString(port); 150 RegionMoverBuilder rmBuilder = new RegionMoverBuilder(rs, TEST_UTIL.getConfiguration()) 151 .ack(false); 152 RegionMover rm = rmBuilder.build(); 153 LOG.info("Unloading " + rs); 154 rm.unload(); 155 TEST_UTIL.waitFor(5000, 500, new Predicate<Exception>() { 156 @Override 157 public boolean evaluate() throws Exception { 158 return regionServer.getNumberOfOnlineRegions() < noRegions; 159 } 160 }); 161 } 162 163 @Test 164 public void testUnloadWithAck() throws Exception { 165 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 166 HRegionServer regionServer = cluster.getRegionServer(0); 167 String rsName = regionServer.getServerName().getHostname(); 168 int port = regionServer.getServerName().getPort(); 169 String rs = rsName + ":" + Integer.toString(port); 170 RegionMoverBuilder rmBuilder = new RegionMoverBuilder(rs, TEST_UTIL.getConfiguration()) 171 .ack(true); 172 RegionMover rm = rmBuilder.build(); 173 rm.unload(); 174 LOG.info("Unloading " + rs); 175 assertEquals(0, regionServer.getNumberOfOnlineRegions()); 176 } 177 178 /** 179 * Test that loading the same region set doesn't cause timeout loop during meta load. 180 */ 181 @Test 182 public void testRepeatedLoad() throws Exception { 183 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 184 HRegionServer regionServer = cluster.getRegionServer(0); 185 String rsName = regionServer.getServerName().getHostname(); 186 int port = regionServer.getServerName().getPort(); 187 String rs = rsName + ":" + Integer.toString(port); 188 RegionMoverBuilder rmBuilder = new RegionMoverBuilder(rs, TEST_UTIL.getConfiguration()) 189 .ack(true); 190 RegionMover rm = rmBuilder.build(); 191 rm.unload(); 192 assertEquals(0, regionServer.getNumberOfOnlineRegions()); 193 rmBuilder = new RegionMoverBuilder(rs, TEST_UTIL.getConfiguration()).ack(true); 194 rm = rmBuilder.build(); 195 rm.load(); 196 rm.load(); //Repeat the same load. It should be very fast because all regions are already moved. 197 } 198 199 /** 200 * To test that we successfully exclude a server from the unloading process We test for the number 201 * of regions on Excluded server and also test that regions are unloaded successfully 202 */ 203 @Test 204 public void testExclude() throws Exception { 205 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 206 File excludeFile = new File(TEST_UTIL.getDataTestDir().toUri().getPath(), "exclude_file"); 207 FileWriter fos = new FileWriter(excludeFile); 208 HRegionServer excludeServer = cluster.getRegionServer(1); 209 String excludeHostname = excludeServer.getServerName().getHostname(); 210 int excludeServerPort = excludeServer.getServerName().getPort(); 211 int regionsExcludeServer = excludeServer.getNumberOfOnlineRegions(); 212 String excludeServerName = excludeHostname + ":" + Integer.toString(excludeServerPort); 213 fos.write(excludeServerName); 214 fos.close(); 215 HRegionServer regionServer = cluster.getRegionServer(0); 216 String rsName = regionServer.getServerName().getHostname(); 217 int port = regionServer.getServerName().getPort(); 218 String rs = rsName + ":" + Integer.toString(port); 219 RegionMoverBuilder rmBuilder = new RegionMoverBuilder(rs, TEST_UTIL.getConfiguration()) 220 .ack(true).excludeFile(excludeFile.getCanonicalPath()); 221 RegionMover rm = rmBuilder.build(); 222 rm.unload(); 223 LOG.info("Unloading " + rs); 224 assertEquals(0, regionServer.getNumberOfOnlineRegions()); 225 assertEquals(regionsExcludeServer, cluster.getRegionServer(1).getNumberOfOnlineRegions()); 226 LOG.info("Before:" + regionsExcludeServer + " After:" 227 + cluster.getRegionServer(1).getNumberOfOnlineRegions()); 228 } 229 230 @Test 231 public void testRegionServerPort() { 232 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 233 HRegionServer regionServer = cluster.getRegionServer(0); 234 String rsName = regionServer.getServerName().getHostname(); 235 236 final int PORT = 16021; 237 Configuration conf = TEST_UTIL.getConfiguration(); 238 String originalPort = conf.get(HConstants.REGIONSERVER_PORT); 239 conf.set(HConstants.REGIONSERVER_PORT, Integer.toString(PORT)); 240 RegionMoverBuilder rmBuilder = new RegionMoverBuilder(rsName, conf); 241 assertEquals(PORT, rmBuilder.port); 242 if (originalPort != null) { 243 conf.set(HConstants.REGIONSERVER_PORT, originalPort); 244 } 245 } 246}