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 * <p>
010 * http://www.apache.org/licenses/LICENSE-2.0
011 * <p>
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.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.MoveRegionState.MOVE_REGION_ASSIGN;
021
022import java.util.List;
023import java.util.concurrent.CountDownLatch;
024
025import org.apache.hadoop.hbase.HBaseClassTestRule;
026import org.apache.hadoop.hbase.HBaseIOException;
027import org.apache.hadoop.hbase.HBaseTestingUtility;
028import org.apache.hadoop.hbase.HRegionLocation;
029import org.apache.hadoop.hbase.MiniHBaseCluster;
030import org.apache.hadoop.hbase.ServerName;
031import org.apache.hadoop.hbase.TableName;
032import org.apache.hadoop.hbase.client.ClusterConnection;
033import org.apache.hadoop.hbase.client.RegionInfo;
034import org.apache.hadoop.hbase.master.HMaster;
035import org.apache.hadoop.hbase.master.RegionPlan;
036import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
037import org.apache.hadoop.hbase.master.procedure.ProcedureSyncWait;
038import org.apache.hadoop.hbase.testclassification.LargeTests;
039import org.junit.AfterClass;
040import org.junit.Assert;
041import org.junit.BeforeClass;
042import org.junit.ClassRule;
043import org.junit.Test;
044import org.junit.experimental.categories.Category;
045import org.slf4j.Logger;
046import org.slf4j.LoggerFactory;
047
048import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos;
049
050@Category({LargeTests.class})
051public class TestMoveSystemTableWithStopMaster {
052
053  private static final Logger LOG =
054    LoggerFactory.getLogger(TestMoveSystemTableWithStopMaster.class);
055
056  @ClassRule
057  public static final HBaseClassTestRule CLASS_RULE =
058    HBaseClassTestRule.forClass(TestMoveSystemTableWithStopMaster.class);
059
060  private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
061
062  @BeforeClass
063  public static void setUp() throws Exception {
064    UTIL.startMiniCluster(1, 2);
065  }
066
067  @AfterClass
068  public static void tearDown() throws Exception {
069    UTIL.shutdownMiniCluster();
070  }
071
072  @Test
073  public void testMoveMetaRegoinWithStopMaster() throws Exception {
074    ClusterConnection conn = (ClusterConnection) UTIL.getConnection();
075    MiniHBaseCluster miniHBaseCluster = UTIL.getHBaseCluster();
076
077    List<HRegionLocation> namespaceRegionLocations = conn.locateRegions(TableName.META_TABLE_NAME);
078
079    RegionInfo regionInfo = namespaceRegionLocations.get(0).getRegion();
080    ServerName source = namespaceRegionLocations.get(0).getServerName();
081    ServerName dstServerName = UTIL.getOtherRegionServer(
082      miniHBaseCluster.getRegionServer(source)).getServerName();
083
084    RegionPlan rp = new RegionPlan(regionInfo, source, dstServerName);
085
086    HMaster master = UTIL.getHBaseCluster().getMaster();
087
088    CountDownLatch moveRegionAssignLatch = new CountDownLatch(1);
089    CountDownLatch masterAbortLatch = new CountDownLatch(1);
090
091    MoveRegionProcedureHoldBeforeAssign proc = new MoveRegionProcedureHoldBeforeAssign(
092      master.getMasterProcedureExecutor().getEnvironment(), rp, true);
093
094    proc.moveRegionAssignLatch = moveRegionAssignLatch;
095    proc.masterStoppedLatch = masterAbortLatch;
096
097    ProcedureSyncWait.submitProcedure(master.getMasterProcedureExecutor(), proc);
098
099    moveRegionAssignLatch.await();
100    master.abort("for test");
101    // may not closed, and rs still conn to old master
102    master.getEventLoopGroupConfig().group().shutdownGracefully();
103    miniHBaseCluster.waitForMasterToStop(master.getServerName(), 30000);
104    masterAbortLatch.countDown();
105
106    UTIL.getMiniHBaseCluster().startMaster();
107
108    // master should be initialized in 30 seconds
109    Assert.assertTrue(miniHBaseCluster.waitForActiveAndReadyMaster(60000));
110  }
111
112
113  @Test
114  public void testMoveNamespaceRegoinWithStopMaster() throws Exception {
115    ClusterConnection conn = (ClusterConnection) UTIL.getConnection();
116    MiniHBaseCluster miniHBaseCluster = UTIL.getHBaseCluster();
117
118    List<HRegionLocation> namespaceRegionLocations = conn.locateRegions(
119      TableName.NAMESPACE_TABLE_NAME);
120
121    RegionInfo regionInfo = namespaceRegionLocations.get(0).getRegion();
122    ServerName source = namespaceRegionLocations.get(0).getServerName();
123    ServerName dstServerName = UTIL.getOtherRegionServer(
124      miniHBaseCluster.getRegionServer(source)).getServerName();
125
126    RegionPlan rp = new RegionPlan(regionInfo, source, dstServerName);
127
128    HMaster master = UTIL.getHBaseCluster().getMaster();
129
130    CountDownLatch moveRegionAssignLatch = new CountDownLatch(1);
131    CountDownLatch masterAbortLatch = new CountDownLatch(1);
132
133    MoveRegionProcedureHoldBeforeAssign proc = new MoveRegionProcedureHoldBeforeAssign(
134      master.getMasterProcedureExecutor().getEnvironment(), rp, true);
135
136    proc.moveRegionAssignLatch = moveRegionAssignLatch;
137    proc.masterStoppedLatch = masterAbortLatch;
138
139    ProcedureSyncWait.submitProcedure(master.getMasterProcedureExecutor(), proc);
140
141    moveRegionAssignLatch.await();
142    master.abort("for test");
143    miniHBaseCluster.waitForMasterToStop(master.getServerName(), 30000);
144    masterAbortLatch.countDown();
145
146    UTIL.getMiniHBaseCluster().startMaster();
147
148    // master should be initialized in 60 seconds
149    Assert.assertTrue(miniHBaseCluster.waitForActiveAndReadyMaster(60000));
150  }
151
152  public static class MoveRegionProcedureHoldBeforeAssign extends MoveRegionProcedure {
153    public MoveRegionProcedureHoldBeforeAssign() {
154    // Required by the Procedure framework to create the procedure on replay
155      super();
156    }
157
158    CountDownLatch masterStoppedLatch;
159
160    CountDownLatch moveRegionAssignLatch;
161
162    public MoveRegionProcedureHoldBeforeAssign(MasterProcedureEnv env,
163      RegionPlan plan, boolean check) throws HBaseIOException {
164      super(env, plan, check);
165    }
166
167    protected Flow executeFromState(final MasterProcedureEnv env,
168      final MasterProcedureProtos.MoveRegionState state) throws InterruptedException {
169      if (state == MOVE_REGION_ASSIGN) {
170        if (moveRegionAssignLatch != null) {
171          moveRegionAssignLatch.countDown();
172          masterStoppedLatch.await();
173        }
174      }
175      return super.executeFromState(env, state);
176    }
177  }
178}