diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
index 4437c31eaa82..01e4e5cd961e 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
@@ -425,6 +425,8 @@ public class HMaster extends HBaseServerBase implements Maste
// the master local storage to store procedure data, meta region locations, etc.
private MasterRegion masterRegion;
+ private RegionServerList rsListStorage;
+
// handle table states
private TableStateManager tableStateManager;
@@ -927,15 +929,18 @@ private void finishActiveMasterInitialization(MonitoredTask status) throws IOExc
status.setStatus("Initialize ServerManager and schedule SCP for crash servers");
// The below two managers must be created before loading procedures, as they will be used during
// loading.
- this.serverManager = createServerManager(this);
+ // initialize master local region
+ masterRegion = MasterRegionFactory.create(this);
+ rsListStorage = new MasterRegionServerList(masterRegion, this);
+
+ this.serverManager = createServerManager(this, rsListStorage);
this.syncReplicationReplayWALManager = new SyncReplicationReplayWALManager(this);
if (!conf.getBoolean(HBASE_SPLIT_WAL_COORDINATED_BY_ZK,
DEFAULT_HBASE_SPLIT_COORDINATED_BY_ZK)) {
this.splitWALManager = new SplitWALManager(this);
}
- // initialize master local region
- masterRegion = MasterRegionFactory.create(this);
+
tryMigrateMetaLocationsFromZooKeeper();
@@ -964,7 +969,8 @@ private void finishActiveMasterInitialization(MonitoredTask status) throws IOExc
this.regionServerTracker.upgrade(
procsByType.getOrDefault(ServerCrashProcedure.class, Collections.emptyList()).stream()
.map(p -> (ServerCrashProcedure) p).map(p -> p.getServerName()).collect(Collectors.toSet()),
- walManager.getLiveServersFromWALDir(), walManager.getSplittingServersFromWALDir());
+ Sets.union(rsListStorage.getAll(), walManager.getLiveServersFromWALDir()),
+ walManager.getSplittingServersFromWALDir());
// This manager must be accessed AFTER hbase:meta is confirmed on line..
this.tableStateManager = new TableStateManager(this);
@@ -1387,11 +1393,12 @@ private void initMobCleaner() {
*
*/
@InterfaceAudience.Private
- protected ServerManager createServerManager(final MasterServices master) throws IOException {
+ protected ServerManager createServerManager(MasterServices master,
+ RegionServerList storage) throws IOException {
// We put this out here in a method so can do a Mockito.spy and stub it out
// w/ a mocked up ServerManager.
setupClusterConnection();
- return new ServerManager(master);
+ return new ServerManager(master, storage);
}
private void waitForRegionServers(final MonitoredTask status)
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRegionServerList.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRegionServerList.java
new file mode 100644
index 000000000000..26ed9e98252c
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRegionServerList.java
@@ -0,0 +1,111 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.master;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.hadoop.hbase.Abortable;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.ServerName;
+import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.log.HBaseMarkers;
+import org.apache.hadoop.hbase.master.assignment.ServerState;
+import org.apache.hadoop.hbase.master.region.MasterRegion;
+import org.apache.hadoop.hbase.master.region.MasterRegionFactory;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.yetus.audience.InterfaceAudience;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link MasterRegion} based {@link RegionServerList}.
+ *
+ * This is useful when we want to restart a cluster with only the data on file system, as when
+ * restarting, we need to get the previous live region servers for scheduling SCP. Before we have
+ * this class, we need to scan the WAL directory on WAL file system to find out the previous live
+ * region servers, which means we can not restart a cluster without the previous WAL file system,
+ * even if we have flushed all the data.
+ *
+ * Please see HBASE-26245 for more details.
+ */
+@InterfaceAudience.Private
+public class MasterRegionServerList implements RegionServerList {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MasterRegionServerList.class);
+
+ private final MasterRegion region;
+
+ private final Abortable abortable;
+
+ public MasterRegionServerList(MasterRegion region, Abortable abortable) {
+ this.region = region;
+ this.abortable = abortable;
+ }
+
+ @Override
+ public void started(ServerName sn) {
+ Put put =
+ new Put(Bytes.toBytes(sn.getServerName())).addColumn(MasterRegionFactory.REGION_SERVER_FAMILY,
+ HConstants.STATE_QUALIFIER, Bytes.toBytes(ServerState.ONLINE.name()));
+ try {
+ region.update(r -> r.put(put));
+ } catch (IOException e) {
+ LOG.error(HBaseMarkers.FATAL, "Failed to record region server {} as started, aborting...", sn,
+ e);
+ abortable.abort("Failed to record region server as started");
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ @Override
+ public void expired(ServerName sn) {
+ Delete delete = new Delete(Bytes.toBytes(sn.getServerName()))
+ .addFamily(MasterRegionFactory.REGION_SERVER_FAMILY);
+ try {
+ region.update(r -> r.delete(delete));
+ } catch (IOException e) {
+ LOG.error(HBaseMarkers.FATAL, "Failed to record region server {} as expired, aborting...", sn,
+ e);
+ abortable.abort("Failed to record region server as expired");
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ @Override
+ public Set getAll() throws IOException {
+ Set rsList = new HashSet<>();
+ try (ResultScanner scanner =
+ region.getScanner(new Scan().addFamily(MasterRegionFactory.REGION_SERVER_FAMILY))) {
+ for (;;) {
+ Result result = scanner.next();
+ if (result == null) {
+ break;
+ }
+ rsList.add(ServerName.valueOf(Bytes.toString(result.getRow())));
+ }
+ }
+ return rsList;
+ }
+
+}
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterWalManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterWalManager.java
index 61b432710d8d..cd92a63a179d 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterWalManager.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterWalManager.java
@@ -158,8 +158,6 @@ private boolean checkFileSystem() {
/**
* Get Servernames which are currently splitting; paths have a '-splitting' suffix.
- * @return ServerName
- * @throws IOException IOException
*/
public Set getSplittingServersFromWALDir() throws IOException {
return getServerNamesFromWALDirPath(
@@ -169,8 +167,6 @@ public Set getSplittingServersFromWALDir() throws IOException {
/**
* Get Servernames that COULD BE 'alive'; excludes those that have a '-splitting' suffix as these
* are already being split -- they cannot be 'alive'.
- * @return ServerName
- * @throws IOException IOException
*/
public Set getLiveServersFromWALDir() throws IOException {
return getServerNamesFromWALDirPath(
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionServerList.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionServerList.java
new file mode 100644
index 000000000000..c7e00b1bb2a5
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionServerList.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.master;
+
+import java.io.IOException;
+import java.util.Set;
+import org.apache.hadoop.hbase.ServerName;
+import org.apache.yetus.audience.InterfaceAudience;
+
+/**
+ * For storing the region server list.
+ *
+ * Mainly be used when restarting master, to load the previous active region server list.
+ */
+@InterfaceAudience.Private
+public interface RegionServerList {
+
+ /**
+ * Called when a region server join the cluster.
+ */
+ void started(ServerName sn);
+
+ /**
+ * Called when a region server is dead.
+ */
+ void expired(ServerName sn);
+
+ /**
+ * Get all live region servers.
+ */
+ Set getAll() throws IOException;
+}
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionServerTracker.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionServerTracker.java
index 65cc7ae57f13..63a3ec19facc 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionServerTracker.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionServerTracker.java
@@ -115,22 +115,22 @@ private RegionServerInfo getServerInfo(ServerName serverName)
* {@link ServerManager#findDeadServersAndProcess(Set, Set)}, we call it here under the lock
* protection to prevent concurrency issues with server expiration operation.
* @param deadServersFromPE the region servers which already have SCP associated.
- * @param liveServersFromWALDir the live region servers from wal directory.
+ * @param liveServersBeforeRestart the live region servers we recorded before master restarts.
* @param splittingServersFromWALDir Servers whose WALs are being actively 'split'.
*/
- public void upgrade(Set deadServersFromPE, Set liveServersFromWALDir,
+ public void upgrade(Set deadServersFromPE, Set liveServersBeforeRestart,
Set splittingServersFromWALDir) throws KeeperException, IOException {
LOG.info(
"Upgrading RegionServerTracker to active master mode; {} have existing" +
"ServerCrashProcedures, {} possibly 'live' servers, and {} 'splitting'.",
- deadServersFromPE.size(), liveServersFromWALDir.size(), splittingServersFromWALDir.size());
+ deadServersFromPE.size(), liveServersBeforeRestart.size(), splittingServersFromWALDir.size());
// deadServersFromPE is made from a list of outstanding ServerCrashProcedures.
// splittingServersFromWALDir are being actively split -- the directory in the FS ends in
// '-SPLITTING'. Each splitting server should have a corresponding SCP. Log if not.
splittingServersFromWALDir.stream().filter(s -> !deadServersFromPE.contains(s)).
forEach(s -> LOG.error("{} has no matching ServerCrashProcedure", s));
// create ServerNode for all possible live servers from wal directory
- liveServersFromWALDir
+ liveServersBeforeRestart
.forEach(sn -> server.getAssignmentManager().getRegionStates().getOrCreateServer(sn));
ServerManager serverManager = server.getServerManager();
synchronized (this) {
@@ -142,7 +142,7 @@ public void upgrade(Set deadServersFromPE, Set liveServe
info.getVersionInfo().getVersion()) : ServerMetricsBuilder.of(serverName);
serverManager.checkAndRecordNewServer(serverName, serverMetrics);
}
- serverManager.findDeadServersAndProcess(deadServersFromPE, liveServersFromWALDir);
+ serverManager.findDeadServersAndProcess(deadServersFromPE, liveServersBeforeRestart);
active = true;
}
}
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java
index 0efedbcafafe..257376045cde 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java
@@ -167,6 +167,7 @@ public class ServerManager {
private final ArrayList drainingServers = new ArrayList<>();
private final MasterServices master;
+ private final RegionServerList storage;
private final DeadServer deadservers = new DeadServer();
@@ -179,13 +180,14 @@ public class ServerManager {
/**
* Constructor.
*/
- public ServerManager(final MasterServices master) {
+ public ServerManager(final MasterServices master, RegionServerList storage) {
this.master = master;
+ this.storage = storage;
Configuration c = master.getConfiguration();
maxSkew = c.getLong(MAX_CLOCK_SKEW_MS, 30000);
warningSkew = c.getLong("hbase.master.warningclockskew", 10000);
- persistFlushedSequenceId = c.getBoolean(PERSIST_FLUSHEDSEQUENCEID,
- PERSIST_FLUSHEDSEQUENCEID_DEFAULT);
+ persistFlushedSequenceId =
+ c.getBoolean(PERSIST_FLUSHEDSEQUENCEID, PERSIST_FLUSHEDSEQUENCEID_DEFAULT);
}
/**
@@ -211,7 +213,6 @@ public boolean unregisterListener(final ServerListener listener) {
* @param version the version of the new regionserver, could contain strings like "SNAPSHOT"
* @param ia the InetAddress from which request is received
* @return The ServerName we know this server as.
- * @throws IOException
*/
ServerName regionServerStartup(RegionServerStartupRequest request, int versionNumber,
String version, InetAddress ia) throws IOException {
@@ -232,13 +233,12 @@ ServerName regionServerStartup(RegionServerStartupRequest request, int versionNu
LOG.warn(
"THIS SHOULD NOT HAPPEN, RegionServerStartup" + " could not record the server: " + sn);
}
+ storage.started(sn);
return sn;
}
/**
* Updates last flushed sequence Ids for the regions on server sn
- * @param sn
- * @param hsl
*/
private void updateLastFlushedSequenceIds(ServerName sn, ServerMetrics hsl) {
for (Entry entry : hsl.getRegionMetrics().entrySet()) {
@@ -611,6 +611,7 @@ synchronized long expireServer(final ServerName serverName, boolean force) {
}
LOG.info("Processing expiration of " + serverName + " on " + this.master.getServerName());
long pid = master.getAssignmentManager().submitServerCrash(serverName, true, force);
+ storage.expired(serverName);
// Tell our listeners that a server was removed
if (!this.listeners.isEmpty()) {
this.listeners.stream().forEach(l -> l.serverRemoved(serverName));
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/MasterRegionFactory.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/MasterRegionFactory.java
index 3ef6224c4d9b..719b994ce160 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/MasterRegionFactory.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/MasterRegionFactory.java
@@ -87,12 +87,16 @@ public final class MasterRegionFactory {
public static final byte[] PROC_FAMILY = Bytes.toBytes("proc");
+ public static final byte[] REGION_SERVER_FAMILY = Bytes.toBytes("rs");
+
private static final TableDescriptor TABLE_DESC = TableDescriptorBuilder.newBuilder(TABLE_NAME)
.setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(HConstants.CATALOG_FAMILY)
.setMaxVersions(HConstants.DEFAULT_HBASE_META_VERSIONS).setInMemory(true)
.setBlocksize(HConstants.DEFAULT_HBASE_META_BLOCK_SIZE).setBloomFilterType(BloomType.ROWCOL)
.setDataBlockEncoding(DataBlockEncoding.ROW_INDEX_V1).build())
- .setColumnFamily(ColumnFamilyDescriptorBuilder.of(PROC_FAMILY)).build();
+ .setColumnFamily(ColumnFamilyDescriptorBuilder.of(PROC_FAMILY))
+ .setColumnFamily(ColumnFamilyDescriptorBuilder.of(REGION_SERVER_FAMILY))
+ .build();
private static TableDescriptor withTrackerConfigs(Configuration conf) {
String trackerImpl = conf.get(TRACKER_IMPL, conf.get(StoreFileTrackerFactory.TRACKER_IMPL,
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/DummyRegionServerListStorage.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/DummyRegionServerListStorage.java
new file mode 100644
index 000000000000..ec657549e340
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/DummyRegionServerListStorage.java
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.master;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+import org.apache.hadoop.hbase.ServerName;
+
+public class DummyRegionServerListStorage implements RegionServerList {
+
+ @Override
+ public void started(ServerName sn) {
+ }
+
+ @Override
+ public void expired(ServerName sn) {
+ }
+
+ @Override
+ public Set getAll() throws IOException {
+ return Collections.emptySet();
+ }
+
+}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestClockSkewDetection.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestClockSkewDetection.java
index dd983cd1a7bf..d1de40c52340 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestClockSkewDetection.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestClockSkewDetection.java
@@ -48,7 +48,8 @@ public class TestClockSkewDetection {
@Test
public void testClockSkewDetection() throws Exception {
final Configuration conf = HBaseConfiguration.create();
- ServerManager sm = new ServerManager(new MockNoopMasterServices(conf));
+ ServerManager sm =
+ new ServerManager(new MockNoopMasterServices(conf), new DummyRegionServerListStorage());
LOG.debug("regionServerStartup 1");
InetAddress ia1 = InetAddress.getLocalHost();
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestRestartWithEmptyWALDirectory.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestRestartWithEmptyWALDirectory.java
new file mode 100644
index 000000000000..c40317a4a923
--- /dev/null
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestRestartWithEmptyWALDirectory.java
@@ -0,0 +1,104 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.master;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.IOException;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.HBaseClassTestRule;
+import org.apache.hadoop.hbase.HBaseTestingUtil;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Table;
+import org.apache.hadoop.hbase.testclassification.MasterTests;
+import org.apache.hadoop.hbase.testclassification.MediumTests;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.CommonFSUtils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+/**
+ * Simulate the scenario described in HBASE-26245, where we clean the WAL directory and try to start
+ * the cluster.
+ */
+@Category({ MasterTests.class, MediumTests.class })
+public class TestRestartWithEmptyWALDirectory {
+
+ @ClassRule
+ public static final HBaseClassTestRule CLASS_RULE =
+ HBaseClassTestRule.forClass(TestRestartWithEmptyWALDirectory.class);
+
+ private static final HBaseTestingUtil UTIL = new HBaseTestingUtil();
+
+ private static TableName NAME = TableName.valueOf("test");
+
+ private static byte[] FAMILY = Bytes.toBytes("family");
+
+ private static byte[] QUALIFIER = Bytes.toBytes("qualifier");
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ // in the test we shutdown the only master and after restarting its port will be changed, so the
+ // default rpc region server can not work
+ UTIL.getConfiguration().set(HConstants.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY,
+ HConstants.ZK_CONNECTION_REGISTRY_CLASS);
+ UTIL.startMiniCluster(1);
+ UTIL.createTable(NAME, FAMILY).close();
+ UTIL.waitTableAvailable(NAME);
+ }
+
+ @AfterClass
+ public static void tearDown() throws IOException {
+ UTIL.shutdownMiniCluster();
+ }
+
+ @Test
+ public void testRestart() throws IOException, InterruptedException {
+ byte[] row = Bytes.toBytes(0);
+ try (Table table = UTIL.getConnection().getTable(NAME)) {
+ table.put(new Put(row).addColumn(FAMILY, QUALIFIER, row));
+ }
+ // flush all in memory data
+ UTIL.flush(TableName.META_TABLE_NAME);
+ UTIL.flush(NAME);
+
+ // stop master first, so when stopping region server, we will not schedule a SCP.
+ UTIL.getMiniHBaseCluster().stopMaster(0).join();
+ UTIL.getMiniHBaseCluster().stopRegionServer(0).join();
+
+ // let's cleanup the WAL directory
+ UTIL.getTestFileSystem().delete(new Path(CommonFSUtils.getWALRootDir(UTIL.getConfiguration()),
+ HConstants.HREGION_LOGDIR_NAME), true);
+
+ // restart the cluster
+ UTIL.getMiniHBaseCluster().startMaster();
+ UTIL.getMiniHBaseCluster().startRegionServer();
+ UTIL.waitTableAvailable(NAME);
+
+ // the start up should succeed and the data should be persist
+ try (Table table = UTIL.getConnection().getTable(NAME)) {
+ assertArrayEquals(row, table.get(new Get(row)).getValue(FAMILY, QUALIFIER));
+ }
+ }
+}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/MockMasterServices.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/MockMasterServices.java
index d22040b3a478..daaf6d83b9b7 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/MockMasterServices.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/MockMasterServices.java
@@ -38,6 +38,7 @@
import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
import org.apache.hadoop.hbase.client.TableState;
+import org.apache.hadoop.hbase.master.DummyRegionServerListStorage;
import org.apache.hadoop.hbase.master.LoadBalancer;
import org.apache.hadoop.hbase.master.MasterFileSystem;
import org.apache.hadoop.hbase.master.MasterServices;
@@ -115,7 +116,7 @@ public MockMasterServices(Configuration conf,
this.assignmentManager =
new AssignmentManager(this, masterRegion, new MockRegionStateStore(this, masterRegion));
this.balancer = LoadBalancerFactory.getLoadBalancer(conf);
- this.serverManager = new ServerManager(this);
+ this.serverManager = new ServerManager(this, new DummyRegionServerListStorage());
this.tableStateManager = Mockito.mock(TableStateManager.class);
Mockito.when(this.tableStateManager.getTableState(Mockito.any())).
thenReturn(new TableState(TableName.valueOf("AnyTableNameSetInMockMasterServcies"),
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionAssignedToMultipleRegionServers.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionAssignedToMultipleRegionServers.java
index 0cc510f06e34..3bcf285e20f4 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionAssignedToMultipleRegionServers.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRegionAssignedToMultipleRegionServers.java
@@ -36,6 +36,7 @@
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.master.MasterServices;
import org.apache.hadoop.hbase.master.RegionPlan;
+import org.apache.hadoop.hbase.master.RegionServerList;
import org.apache.hadoop.hbase.master.ServerManager;
import org.apache.hadoop.hbase.master.region.MasterRegion;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
@@ -69,8 +70,8 @@ public class TestRegionAssignedToMultipleRegionServers {
private static final class ServerManagerForTest extends ServerManager {
- public ServerManagerForTest(MasterServices master) {
- super(master);
+ public ServerManagerForTest(MasterServices master, RegionServerList storage) {
+ super(master, storage);
}
@Override
@@ -121,9 +122,10 @@ protected AssignmentManager createAssignmentManager(MasterServices master,
}
@Override
- protected ServerManager createServerManager(MasterServices master) throws IOException {
+ protected ServerManager createServerManager(MasterServices master,
+ RegionServerList storage) throws IOException {
setupClusterConnection();
- return new ServerManagerForTest(master);
+ return new ServerManagerForTest(master, storage);
}
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportRegionStateTransitionFromDeadServer.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportRegionStateTransitionFromDeadServer.java
index 7fbf28bce0c2..8dd51d528776 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportRegionStateTransitionFromDeadServer.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportRegionStateTransitionFromDeadServer.java
@@ -39,6 +39,7 @@
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.master.MasterServices;
import org.apache.hadoop.hbase.master.RegionPlan;
+import org.apache.hadoop.hbase.master.RegionServerList;
import org.apache.hadoop.hbase.master.ServerManager;
import org.apache.hadoop.hbase.master.region.MasterRegion;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
@@ -71,8 +72,8 @@ public class TestReportRegionStateTransitionFromDeadServer {
private static final class ServerManagerForTest extends ServerManager {
- public ServerManagerForTest(MasterServices master) {
- super(master);
+ public ServerManagerForTest(MasterServices master, RegionServerList storage) {
+ super(master, storage);
}
@Override
@@ -128,9 +129,10 @@ protected AssignmentManager createAssignmentManager(MasterServices master,
}
@Override
- protected ServerManager createServerManager(MasterServices master) throws IOException {
+ protected ServerManager createServerManager(MasterServices master,
+ RegionServerList storage) throws IOException {
setupClusterConnection();
- return new ServerManagerForTest(master);
+ return new ServerManagerForTest(master, storage);
}
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestSCPGetRegionsRace.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestSCPGetRegionsRace.java
index c4ad67c43ca9..f1f6e719820c 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestSCPGetRegionsRace.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestSCPGetRegionsRace.java
@@ -36,6 +36,7 @@
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.master.MasterServices;
import org.apache.hadoop.hbase.master.RegionPlan;
+import org.apache.hadoop.hbase.master.RegionServerList;
import org.apache.hadoop.hbase.master.ServerManager;
import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure;
import org.apache.hadoop.hbase.master.region.MasterRegion;
@@ -70,8 +71,8 @@ public class TestSCPGetRegionsRace {
private static final class ServerManagerForTest extends ServerManager {
- public ServerManagerForTest(MasterServices master) {
- super(master);
+ public ServerManagerForTest(MasterServices master, RegionServerList storage) {
+ super(master, storage);
}
@Override
@@ -141,9 +142,10 @@ protected AssignmentManager createAssignmentManager(MasterServices master,
}
@Override
- protected ServerManager createServerManager(MasterServices master) throws IOException {
+ protected ServerManager createServerManager(MasterServices master,
+ RegionServerList storage) throws IOException {
setupClusterConnection();
- return new ServerManagerForTest(master);
+ return new ServerManagerForTest(master, storage);
}
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestWakeUpUnexpectedProcedure.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestWakeUpUnexpectedProcedure.java
index 1bfd8ae46540..59c381de0424 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestWakeUpUnexpectedProcedure.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestWakeUpUnexpectedProcedure.java
@@ -36,6 +36,7 @@
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.master.MasterServices;
import org.apache.hadoop.hbase.master.RegionPlan;
+import org.apache.hadoop.hbase.master.RegionServerList;
import org.apache.hadoop.hbase.master.RegionState;
import org.apache.hadoop.hbase.master.ServerManager;
import org.apache.hadoop.hbase.master.region.MasterRegion;
@@ -165,8 +166,8 @@ public ReportRegionStateTransitionResponse reportRegionStateTransition(
private static final class SMForTest extends ServerManager {
- public SMForTest(MasterServices master) {
- super(master);
+ public SMForTest(MasterServices master, RegionServerList storage) {
+ super(master, storage);
}
@Override
@@ -209,9 +210,10 @@ protected AssignmentManager createAssignmentManager(MasterServices master,
}
@Override
- protected ServerManager createServerManager(MasterServices master) throws IOException {
+ protected ServerManager createServerManager(MasterServices master,
+ RegionServerList storage) throws IOException {
setupClusterConnection();
- return new SMForTest(master);
+ return new SMForTest(master, storage);
}
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/TestClaimReplicationQueue.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/TestClaimReplicationQueue.java
index 6c86feb70b31..41f55a252237 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/TestClaimReplicationQueue.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/TestClaimReplicationQueue.java
@@ -28,6 +28,7 @@
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.master.MasterServices;
+import org.apache.hadoop.hbase.master.RegionServerList;
import org.apache.hadoop.hbase.master.ServerManager;
import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure;
import org.apache.hadoop.hbase.master.replication.ClaimReplicationQueuesProcedure;
@@ -67,8 +68,8 @@ public class TestClaimReplicationQueue extends TestReplicationBase {
public static final class ServerManagerForTest extends ServerManager {
- public ServerManagerForTest(MasterServices master) {
- super(master);
+ public ServerManagerForTest(MasterServices master, RegionServerList storage) {
+ super(master, storage);
}
@Override
@@ -92,9 +93,10 @@ public HMasterForTest(Configuration conf) throws IOException {
}
@Override
- protected ServerManager createServerManager(MasterServices master) throws IOException {
+ protected ServerManager createServerManager(MasterServices master,
+ RegionServerList storage) throws IOException {
setupClusterConnection();
- return new ServerManagerForTest(master);
+ return new ServerManagerForTest(master, storage);
}
}