1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 package org.apache.hadoop.hbase.master; 19 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertNotNull; 23 import static org.mockito.Mockito.when; 24 25 import java.io.IOException; 26 import java.util.Collection; 27 import java.util.Iterator; 28 import java.util.List; 29 30 import org.apache.commons.logging.Log; 31 import org.apache.commons.logging.LogFactory; 32 import org.apache.hadoop.conf.Configuration; 33 import org.apache.hadoop.hbase.*; 34 import org.apache.hadoop.hbase.coordination.BaseCoordinatedStateManager; 35 import org.apache.hadoop.hbase.coordination.OpenRegionCoordination; 36 import org.apache.hadoop.hbase.coordination.ZkCoordinatedStateManager; 37 import org.apache.hadoop.hbase.coordination.ZkOpenRegionCoordination; 38 import org.apache.hadoop.hbase.executor.EventType; 39 import org.apache.hadoop.hbase.master.handler.OpenedRegionHandler; 40 import org.apache.hadoop.hbase.regionserver.HRegion; 41 import org.apache.hadoop.hbase.regionserver.HRegionServer; 42 import org.apache.hadoop.hbase.regionserver.Region; 43 import org.apache.hadoop.hbase.testclassification.MediumTests; 44 import org.apache.hadoop.hbase.util.Bytes; 45 import org.apache.hadoop.hbase.util.MockServer; 46 import org.apache.hadoop.hbase.zookeeper.ZKAssign; 47 import org.apache.hadoop.hbase.zookeeper.ZKTableStateManager; 48 import org.apache.hadoop.hbase.zookeeper.ZKUtil; 49 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; 50 import org.apache.zookeeper.KeeperException; 51 import org.apache.zookeeper.data.Stat; 52 import org.junit.After; 53 import org.junit.Before; 54 import org.junit.Test; 55 import org.junit.experimental.categories.Category; 56 import org.mockito.Mockito; 57 58 @Category(MediumTests.class) 59 public class TestOpenedRegionHandler { 60 61 private static final Log LOG = LogFactory 62 .getLog(TestOpenedRegionHandler.class); 63 64 private HBaseTestingUtility TEST_UTIL; 65 private final int NUM_MASTERS = 1; 66 private final int NUM_RS = 1; 67 private Configuration conf; 68 private Configuration resetConf; 69 private ZooKeeperWatcher zkw; 70 71 @Before setUp()72 public void setUp() throws Exception { 73 conf = HBaseConfiguration.create(); 74 conf.setBoolean("hbase.assignment.usezk", true); 75 TEST_UTIL = HBaseTestingUtility.createLocalHTU(conf); 76 } 77 78 @After tearDown()79 public void tearDown() throws Exception { 80 // Stop the cluster 81 TEST_UTIL.shutdownMiniCluster(); 82 TEST_UTIL = new HBaseTestingUtility(resetConf); 83 } 84 85 @Test testOpenedRegionHandlerOnMasterRestart()86 public void testOpenedRegionHandlerOnMasterRestart() throws Exception { 87 // Start the cluster 88 log("Starting cluster"); 89 conf = HBaseConfiguration.create(); 90 conf.setBoolean("hbase.assignment.usezk", true); 91 resetConf = conf; 92 TEST_UTIL = new HBaseTestingUtility(conf); 93 TEST_UTIL.startMiniCluster(NUM_MASTERS, NUM_RS); 94 String tableName = "testOpenedRegionHandlerOnMasterRestart"; 95 MiniHBaseCluster cluster = createRegions(tableName); 96 abortMaster(cluster); 97 98 HRegionServer regionServer = cluster.getRegionServer(0); 99 Region region = getRegionBeingServed(cluster, regionServer); 100 101 // forcefully move a region to OPENED state in zk 102 // Create a ZKW to use in the test 103 zkw = HBaseTestingUtility.createAndForceNodeToOpenedState(TEST_UTIL, 104 region, regionServer.getServerName()); 105 106 // Start up a new master 107 log("Starting up a new master"); 108 cluster.startMaster().getMaster(); 109 log("Waiting for master to be ready"); 110 cluster.waitForActiveAndReadyMaster(); 111 log("Master is ready"); 112 113 // Failover should be completed, now wait for no RIT 114 log("Waiting for no more RIT"); 115 ZKAssign.blockUntilNoRIT(zkw); 116 } 117 @Test testShouldNotCompeleteOpenedRegionSuccessfullyIfVersionMismatches()118 public void testShouldNotCompeleteOpenedRegionSuccessfullyIfVersionMismatches() 119 throws Exception { 120 HRegion region = null; 121 try { 122 int testIndex = 0; 123 TEST_UTIL.startMiniZKCluster(); 124 final Server server = new MockServer(TEST_UTIL); 125 HTableDescriptor htd = new HTableDescriptor( 126 TableName.valueOf("testShouldNotCompeleteOpenedRegionSuccessfullyIfVersionMismatches")); 127 HRegionInfo hri = new HRegionInfo(htd.getTableName(), 128 Bytes.toBytes(testIndex), Bytes.toBytes(testIndex + 1)); 129 region = HRegion.createHRegion(hri, TEST_UTIL.getDataTestDir(), TEST_UTIL.getConfiguration(), htd); 130 assertNotNull(region); 131 AssignmentManager am = Mockito.mock(AssignmentManager.class); 132 RegionStates rsm = Mockito.mock(RegionStates.class); 133 Mockito.doReturn(rsm).when(am).getRegionStates(); 134 when(rsm.isRegionInTransition(hri)).thenReturn(false); 135 when(rsm.getRegionState(hri)).thenReturn( 136 new RegionState(region.getRegionInfo(), RegionState.State.OPEN, 137 System.currentTimeMillis(), server.getServerName())); 138 // create a node with OPENED state 139 zkw = HBaseTestingUtility.createAndForceNodeToOpenedState(TEST_UTIL, 140 region, server.getServerName()); 141 when(am.getTableStateManager()).thenReturn(new ZKTableStateManager(zkw)); 142 Stat stat = new Stat(); 143 String nodeName = ZKAssign.getNodeName(zkw, region.getRegionInfo() 144 .getEncodedName()); 145 ZKUtil.getDataAndWatch(zkw, nodeName, stat); 146 147 // use the version for the OpenedRegionHandler 148 BaseCoordinatedStateManager csm = new ZkCoordinatedStateManager(); 149 csm.initialize(server); 150 csm.start(); 151 152 OpenRegionCoordination orc = csm.getOpenRegionCoordination(); 153 ZkOpenRegionCoordination.ZkOpenRegionDetails zkOrd = 154 new ZkOpenRegionCoordination.ZkOpenRegionDetails(); 155 zkOrd.setServerName(server.getServerName()); 156 zkOrd.setVersion(stat.getVersion()); 157 OpenedRegionHandler handler = new OpenedRegionHandler(server, am, region 158 .getRegionInfo(), orc, zkOrd); 159 // Once again overwrite the same znode so that the version changes. 160 ZKAssign.transitionNode(zkw, region.getRegionInfo(), server 161 .getServerName(), EventType.RS_ZK_REGION_OPENED, 162 EventType.RS_ZK_REGION_OPENED, stat.getVersion()); 163 164 // Should not invoke assignmentmanager.regionOnline. If it is 165 // invoked as per current mocking it will throw null pointer exception. 166 boolean expectedException = false; 167 try { 168 handler.process(); 169 } catch (Exception e) { 170 expectedException = true; 171 } 172 assertFalse("The process method should not throw any exception.", 173 expectedException); 174 List<String> znodes = ZKUtil.listChildrenAndWatchForNewChildren(zkw, 175 zkw.assignmentZNode); 176 String regionName = znodes.get(0); 177 assertEquals("The region should not be opened successfully.", regionName, 178 region.getRegionInfo().getEncodedName()); 179 } finally { 180 HRegion.closeHRegion(region); 181 TEST_UTIL.shutdownMiniZKCluster(); 182 } 183 } createRegions(String tableName)184 private MiniHBaseCluster createRegions(String tableName) 185 throws InterruptedException, ZooKeeperConnectionException, IOException, 186 KeeperException { 187 MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster(); 188 log("Waiting for active/ready master"); 189 cluster.waitForActiveAndReadyMaster(); 190 zkw = new ZooKeeperWatcher(conf, "testOpenedRegionHandler", null); 191 192 // Create a table with regions 193 byte[] table = Bytes.toBytes(tableName); 194 byte[] family = Bytes.toBytes("family"); 195 TEST_UTIL.createTable(table, family); 196 197 //wait till the regions are online 198 log("Waiting for no more RIT"); 199 ZKAssign.blockUntilNoRIT(zkw); 200 201 return cluster; 202 } abortMaster(MiniHBaseCluster cluster)203 private void abortMaster(MiniHBaseCluster cluster) { 204 // Stop the master 205 log("Aborting master"); 206 cluster.abortMaster(0); 207 cluster.waitOnMaster(0); 208 log("Master has aborted"); 209 } getRegionBeingServed(MiniHBaseCluster cluster, HRegionServer regionServer)210 private Region getRegionBeingServed(MiniHBaseCluster cluster, 211 HRegionServer regionServer) { 212 Collection<Region> onlineRegionsLocalContext = regionServer 213 .getOnlineRegionsLocalContext(); 214 Iterator<Region> iterator = onlineRegionsLocalContext.iterator(); 215 Region region = null; 216 while (iterator.hasNext()) { 217 region = iterator.next(); 218 if (!region.getRegionInfo().isMetaTable()) { 219 break; 220 } 221 } 222 return region; 223 } log(String msg)224 private void log(String msg) { 225 LOG.debug("\n\nTRR: " + msg + "\n"); 226 } 227 228 } 229 230