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.assertEquals;
021import static org.junit.Assert.assertNotNull;
022
023import java.io.IOException;
024import java.util.Set;
025import org.apache.hadoop.hbase.HBaseTestingUtility;
026import org.apache.hadoop.hbase.ServerName;
027import org.apache.hadoop.hbase.Waiter;
028import org.apache.hadoop.hbase.Waiter.ExplainingPredicate;
029import org.apache.hadoop.hbase.client.RegionInfo;
030import org.apache.hadoop.hbase.master.HMaster;
031import org.apache.hadoop.hbase.master.RegionState.State;
032import org.apache.hadoop.hbase.master.assignment.RegionStates.RegionStateNode;
033import org.apache.hadoop.hbase.master.procedure.ProcedureSyncWait;
034import org.apache.hadoop.hbase.util.Threads;
035import org.apache.yetus.audience.InterfaceAudience;
036import org.apache.yetus.audience.InterfaceStability;
037import org.slf4j.Logger;
038import org.slf4j.LoggerFactory;
039
040@InterfaceAudience.Private
041@InterfaceStability.Evolving
042public final class AssignmentTestingUtil {
043  private static final Logger LOG = LoggerFactory.getLogger(AssignmentTestingUtil.class);
044
045  private AssignmentTestingUtil() {}
046
047  public static void waitForRegionToBeInTransition(final HBaseTestingUtility util,
048      final RegionInfo hri) throws Exception {
049    while (!getMaster(util).getAssignmentManager().getRegionStates().isRegionInTransition(hri)) {
050      Threads.sleep(10);
051    }
052  }
053
054  public static void waitForRsToBeDead(final HBaseTestingUtility util,
055      final ServerName serverName) throws Exception {
056    util.waitFor(60000, new ExplainingPredicate<Exception>() {
057      @Override
058      public boolean evaluate() {
059        return getMaster(util).getServerManager().isServerDead(serverName);
060      }
061
062      @Override
063      public String explainFailure() {
064        return "Server " + serverName + " is not dead";
065      }
066    });
067  }
068
069  public static void stopRs(final HBaseTestingUtility util, final ServerName serverName)
070      throws Exception {
071    LOG.info("STOP REGION SERVER " + serverName);
072    util.getMiniHBaseCluster().stopRegionServer(serverName);
073    waitForRsToBeDead(util, serverName);
074  }
075
076  public static void killRs(final HBaseTestingUtility util, final ServerName serverName)
077      throws Exception {
078    LOG.info("KILL REGION SERVER " + serverName);
079    util.getMiniHBaseCluster().killRegionServer(serverName);
080    waitForRsToBeDead(util, serverName);
081  }
082
083  public static void crashRs(final HBaseTestingUtility util, final ServerName serverName,
084      final boolean kill) throws Exception {
085    if (kill) {
086      killRs(util, serverName);
087    } else {
088      stopRs(util, serverName);
089    }
090  }
091
092  public static ServerName crashRsWithRegion(final HBaseTestingUtility util,
093      final RegionInfo hri, final boolean kill) throws Exception {
094    ServerName serverName = getServerHoldingRegion(util, hri);
095    crashRs(util, serverName, kill);
096    return serverName;
097  }
098
099  public static ServerName getServerHoldingRegion(final HBaseTestingUtility util,
100      final RegionInfo hri) throws Exception {
101    ServerName serverName = util.getMiniHBaseCluster().getServerHoldingRegion(
102      hri.getTable(), hri.getRegionName());
103    ServerName amServerName = getMaster(util).getAssignmentManager().getRegionStates()
104      .getRegionServerOfRegion(hri);
105
106    // Make sure AM and MiniCluster agrees on the Server holding the region
107    // and that the server is online.
108    assertEquals(amServerName, serverName);
109    assertEquals(true, getMaster(util).getServerManager().isServerOnline(serverName));
110    return serverName;
111  }
112
113  public static boolean isServerHoldingMeta(final HBaseTestingUtility util,
114      final ServerName serverName) throws Exception {
115    for (RegionInfo hri: getMetaRegions(util)) {
116      if (serverName.equals(getServerHoldingRegion(util, hri))) {
117        return true;
118      }
119    }
120    return false;
121  }
122
123  public static Set<RegionInfo> getMetaRegions(final HBaseTestingUtility util) {
124    return getMaster(util).getAssignmentManager().getMetaRegionSet();
125  }
126
127  private static HMaster getMaster(final HBaseTestingUtility util) {
128    return util.getMiniHBaseCluster().getMaster();
129  }
130
131  public static boolean waitForAssignment(AssignmentManager am, RegionInfo regionInfo)
132      throws IOException {
133    // This method can be called before the regionInfo has made it into the regionStateMap
134    // so wait around here a while.
135    Waiter.waitFor(am.getConfiguration(), 10000,
136      () -> am.getRegionStates().getRegionStateNode(regionInfo) != null);
137    RegionStateNode regionNode = am.getRegionStates().getRegionStateNode(regionInfo);
138    // Wait until the region has already been open, or we have a TRSP along with it.
139    Waiter.waitFor(am.getConfiguration(), 30000,
140      () -> regionNode.isInState(State.OPEN) || regionNode.isInTransition());
141    RegionTransitionProcedure proc = regionNode.getProcedure();
142    synchronized (regionNode) {
143      if (regionNode.isInState(State.OPEN)) {
144        return true;
145      }
146      proc = regionNode.getProcedure();
147    }
148    assertNotNull(proc);
149    ProcedureSyncWait.waitForProcedureToCompleteIOE(am.getMaster().getMasterProcedureExecutor(),
150      proc, 5L * 60 * 1000);
151    return true;
152  }
153}