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.HBaseTestingUtil;
026import org.apache.hadoop.hbase.ServerName;
027import org.apache.hadoop.hbase.TableName;
028import org.apache.hadoop.hbase.Waiter;
029import org.apache.hadoop.hbase.Waiter.ExplainingPredicate;
030import org.apache.hadoop.hbase.client.Put;
031import org.apache.hadoop.hbase.client.RegionInfo;
032import org.apache.hadoop.hbase.client.Table;
033import org.apache.hadoop.hbase.master.HMaster;
034import org.apache.hadoop.hbase.master.RegionState.State;
035import org.apache.hadoop.hbase.master.procedure.ProcedureSyncWait;
036import org.apache.hadoop.hbase.util.Bytes;
037import org.apache.hadoop.hbase.util.Threads;
038import org.apache.yetus.audience.InterfaceAudience;
039import org.apache.yetus.audience.InterfaceStability;
040import org.slf4j.Logger;
041import org.slf4j.LoggerFactory;
042
043@InterfaceAudience.Private
044@InterfaceStability.Evolving
045public final class AssignmentTestingUtil {
046  private static final Logger LOG = LoggerFactory.getLogger(AssignmentTestingUtil.class);
047
048  private AssignmentTestingUtil() {
049  }
050
051  public static void waitForRegionToBeInTransition(final HBaseTestingUtil util,
052    final RegionInfo hri) throws Exception {
053    while (!getMaster(util).getAssignmentManager().getRegionStates().isRegionInTransition(hri)) {
054      Threads.sleep(10);
055    }
056  }
057
058  public static void waitForRsToBeDead(final HBaseTestingUtil util, final ServerName serverName)
059    throws Exception {
060    util.waitFor(60000, new ExplainingPredicate<Exception>() {
061      @Override
062      public boolean evaluate() {
063        return getMaster(util).getServerManager().isServerDead(serverName);
064      }
065
066      @Override
067      public String explainFailure() {
068        return "Server " + serverName + " is not dead";
069      }
070    });
071  }
072
073  public static void stopRs(final HBaseTestingUtil util, final ServerName serverName)
074    throws Exception {
075    LOG.info("STOP REGION SERVER " + serverName);
076    util.getMiniHBaseCluster().stopRegionServer(serverName);
077    waitForRsToBeDead(util, serverName);
078  }
079
080  public static void killRs(final HBaseTestingUtil util, final ServerName serverName)
081    throws Exception {
082    LOG.info("KILL REGION SERVER " + serverName);
083    util.getMiniHBaseCluster().killRegionServer(serverName);
084    waitForRsToBeDead(util, serverName);
085  }
086
087  public static void crashRs(final HBaseTestingUtil util, final ServerName serverName,
088    final boolean kill) throws Exception {
089    if (kill) {
090      killRs(util, serverName);
091    } else {
092      stopRs(util, serverName);
093    }
094  }
095
096  public static ServerName crashRsWithRegion(final HBaseTestingUtil util, final RegionInfo hri,
097    final boolean kill) throws Exception {
098    ServerName serverName = getServerHoldingRegion(util, hri);
099    crashRs(util, serverName, kill);
100    return serverName;
101  }
102
103  public static ServerName getServerHoldingRegion(final HBaseTestingUtil util, final RegionInfo hri)
104    throws Exception {
105    ServerName serverName =
106      util.getMiniHBaseCluster().getServerHoldingRegion(hri.getTable(), hri.getRegionName());
107    ServerName amServerName =
108      getMaster(util).getAssignmentManager().getRegionStates().getRegionServerOfRegion(hri);
109
110    // Make sure AM and MiniCluster agrees on the Server holding the region
111    // and that the server is online.
112    assertEquals(amServerName, serverName);
113    assertEquals(true, getMaster(util).getServerManager().isServerOnline(serverName));
114    return serverName;
115  }
116
117  public static boolean isServerHoldingMeta(final HBaseTestingUtil util,
118    final ServerName serverName) throws Exception {
119    for (RegionInfo hri : getMetaRegions(util)) {
120      if (serverName.equals(getServerHoldingRegion(util, hri))) {
121        return true;
122      }
123    }
124    return false;
125  }
126
127  public static Set<RegionInfo> getMetaRegions(final HBaseTestingUtil util) {
128    return getMaster(util).getAssignmentManager().getMetaRegionSet();
129  }
130
131  private static HMaster getMaster(final HBaseTestingUtil util) {
132    return util.getMiniHBaseCluster().getMaster();
133  }
134
135  public static boolean waitForAssignment(AssignmentManager am, RegionInfo regionInfo)
136    throws IOException {
137    // This method can be called before the regionInfo has made it into the regionStateMap
138    // so wait around here a while.
139    Waiter.waitFor(am.getConfiguration(), 10000,
140      () -> am.getRegionStates().getRegionStateNode(regionInfo) != null);
141    RegionStateNode regionNode = am.getRegionStates().getRegionStateNode(regionInfo);
142    // Wait until the region has already been open, or we have a TRSP along with it.
143    Waiter.waitFor(am.getConfiguration(), 30000,
144      () -> regionNode.isInState(State.OPEN) || regionNode.isInTransition());
145    TransitRegionStateProcedure proc = regionNode.getProcedure();
146    regionNode.lock();
147    try {
148      if (regionNode.isInState(State.OPEN)) {
149        return true;
150      }
151      proc = regionNode.getProcedure();
152    } finally {
153      regionNode.unlock();
154    }
155    assertNotNull(proc);
156    ProcedureSyncWait.waitForProcedureToCompleteIOE(am.getMaster().getMasterProcedureExecutor(),
157      proc, 5L * 60 * 1000);
158    return true;
159  }
160
161  public static void insertData(final HBaseTestingUtil UTIL, final TableName tableName,
162    int rowCount, int startRowNum, String... cfs) throws IOException {
163    insertData(UTIL, tableName, rowCount, startRowNum, false, cfs);
164  }
165
166  public static void insertData(final HBaseTestingUtil UTIL, final TableName tableName,
167    int rowCount, int startRowNum, boolean flushOnce, String... cfs) throws IOException {
168    Table t = UTIL.getConnection().getTable(tableName);
169    Put p;
170    for (int i = 0; i < rowCount / 2; i++) {
171      p = new Put(Bytes.toBytes("" + (startRowNum + i)));
172      for (String cf : cfs) {
173        p.addColumn(Bytes.toBytes(cf), Bytes.toBytes("q"), Bytes.toBytes(i));
174      }
175      t.put(p);
176      p = new Put(Bytes.toBytes("" + (startRowNum + rowCount - i - 1)));
177      for (String cf : cfs) {
178        p.addColumn(Bytes.toBytes(cf), Bytes.toBytes("q"), Bytes.toBytes(i));
179      }
180      t.put(p);
181      if (i % 5 == 0 && !flushOnce) {
182        UTIL.getAdmin().flush(tableName);
183      }
184    }
185    if (flushOnce) {
186      UTIL.getAdmin().flush(tableName);
187    }
188  }
189}