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.master.assignment; 019 020import static org.junit.Assert.assertTrue; 021 022import java.io.IOException; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.List; 026import java.util.concurrent.CountDownLatch; 027 028import org.apache.hadoop.hbase.HBaseClassTestRule; 029import org.apache.hadoop.hbase.HBaseTestingUtility; 030import org.apache.hadoop.hbase.TableName; 031import org.apache.hadoop.hbase.client.Admin; 032import org.apache.hadoop.hbase.client.RegionInfo; 033import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; 034import org.apache.hadoop.hbase.procedure2.Procedure; 035import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos; 036import org.apache.hadoop.hbase.util.Bytes; 037 038import org.junit.AfterClass; 039import org.junit.Before; 040import org.junit.BeforeClass; 041import org.junit.ClassRule; 042import org.junit.Rule; 043import org.junit.Test; 044import org.junit.experimental.categories.Category; 045import org.junit.rules.TestName; 046import org.slf4j.Logger; 047import org.slf4j.LoggerFactory; 048 049import org.apache.hadoop.hbase.testclassification.LargeTests; 050 051/** 052 * Tests bypass on a region assign/unassign 053 */ 054@Category({LargeTests.class}) 055public class TestRegionBypass { 056 private final static Logger LOG = LoggerFactory.getLogger(TestRegionBypass.class); 057 058 @ClassRule 059 public static final HBaseClassTestRule CLASS_RULE = 060 HBaseClassTestRule.forClass(TestRegionBypass.class); 061 062 @Rule 063 public TestName name = new TestName(); 064 065 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 066 private TableName tableName; 067 068 @BeforeClass 069 public static void startCluster() throws Exception { 070 TEST_UTIL.startMiniCluster(2); 071 } 072 073 @AfterClass 074 public static void stopCluster() throws Exception { 075 TEST_UTIL.shutdownMiniCluster(); 076 } 077 078 @Before 079 public void before() throws IOException { 080 this.tableName = TableName.valueOf(this.name.getMethodName()); 081 // Create a table. Has one region at least. 082 TEST_UTIL.createTable(this.tableName, Bytes.toBytes("cf")); 083 084 } 085 086 @Test 087 public void testBypass() throws IOException { 088 Admin admin = TEST_UTIL.getAdmin(); 089 List<RegionInfo> regions = admin.getRegions(this.tableName); 090 for (RegionInfo ri: regions) { 091 admin.unassign(ri.getRegionName(), false); 092 } 093 List<Long> pids = new ArrayList<>(regions.size()); 094 for (RegionInfo ri: regions) { 095 Procedure<MasterProcedureEnv> p = new StallingAssignProcedure(ri); 096 pids.add(TEST_UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor(). 097 submitProcedure(p)); 098 } 099 for (Long pid: pids) { 100 while (!TEST_UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor().isStarted(pid)) { 101 Thread.currentThread().yield(); 102 } 103 } 104 // Call bypass on all. We should be stuck in the dispatch at this stage. 105 List<Procedure<MasterProcedureEnv>> ps = 106 TEST_UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor().getProcedures(); 107 for (Procedure<MasterProcedureEnv> p: ps) { 108 if (p instanceof StallingAssignProcedure) { 109 List<Boolean> bs = TEST_UTIL.getHbck(). 110 bypassProcedure(Arrays.<Long>asList(p.getProcId()), 1, false, false); 111 for (Boolean b: bs) { 112 LOG.info("BYPASSED {} {}", p.getProcId(), b); 113 } 114 } 115 } 116 // Countdown the latch so its not hanging out. 117 for (Procedure<MasterProcedureEnv> p: ps) { 118 if (p instanceof StallingAssignProcedure) { 119 ((StallingAssignProcedure)p).latch.countDown(); 120 } 121 } 122 // Try and assign WITHOUT override flag. Should fail!. 123 for (RegionInfo ri: regions) { 124 try { 125 admin.assign(ri.getRegionName()); 126 } catch (Throwable dnrioe) { 127 // Expected 128 LOG.info("Expected {}", dnrioe); 129 } 130 } 131 while (!TEST_UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor(). 132 getActiveProcIds().isEmpty()) { 133 Thread.currentThread().yield(); 134 } 135 // Now assign with the override flag. 136 for (RegionInfo ri: regions) { 137 TEST_UTIL.getHbck().assigns(Arrays.<String>asList(ri.getEncodedName()), true); 138 } 139 while (!TEST_UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor(). 140 getActiveProcIds().isEmpty()) { 141 Thread.currentThread().yield(); 142 } 143 for (RegionInfo ri: regions) { 144 assertTrue(ri.toString(), TEST_UTIL.getMiniHBaseCluster().getMaster().getAssignmentManager(). 145 getRegionStates().isRegionOnline(ri)); 146 } 147 } 148 149 /** 150 * An AssignProcedure that Stalls just before the finish. 151 */ 152 public static class StallingAssignProcedure extends AssignProcedure { 153 public final CountDownLatch latch = new CountDownLatch(2); 154 155 public StallingAssignProcedure() { 156 super(); 157 } 158 159 public StallingAssignProcedure(RegionInfo regionInfo) { 160 super(regionInfo); 161 } 162 163 @Override 164 void setTransitionState(MasterProcedureProtos.RegionTransitionState state) { 165 if (state == MasterProcedureProtos.RegionTransitionState.REGION_TRANSITION_DISPATCH) { 166 try { 167 LOG.info("LATCH2 {}", this.latch.getCount()); 168 this.latch.await(); 169 LOG.info("LATCH3 {}", this.latch.getCount()); 170 } catch (InterruptedException e) { 171 e.printStackTrace(); 172 } 173 } else if (state == MasterProcedureProtos.RegionTransitionState.REGION_TRANSITION_QUEUE) { 174 // Set latch. 175 LOG.info("LATCH1 {}", this.latch.getCount()); 176 this.latch.countDown(); 177 } 178 super.setTransitionState(state); 179 } 180 } 181}