This is an automated email from the ASF dual-hosted git repository. zhangduo pushed a commit to branch HASE-24950 in repository https://gitbox.apache.org/repos/asf/hbase.git
commit f63a408772b80c0c287c43ff2c5902bc96b20205 Author: Duo Zhang <zhang...@apache.org> AuthorDate: Mon Sep 21 20:32:15 2020 +0800 HBASE-25013 Avoid reset the backup master root cache every time when syncing (#2392) Signed-off-by: Guanghao Zhang <zg...@apache.org> --- .../org/apache/hadoop/hbase/MetaTableAccessor.java | 21 +-- .../hadoop/hbase/ClientMetaTableAccessor.java | 23 ++++ .../hadoop/hbase/client/ConnectionUtils.java | 39 +----- .../apache/hadoop/hbase/client/MasterRegistry.java | 11 +- .../hadoop/hbase/client/ZKConnectionRegistry.java | 25 +++- .../src/main/protobuf/server/master/Master.proto | 14 ++ .../hbase/client/AsyncClusterConnection.java | 3 +- .../hbase/client/AsyncClusterConnectionImpl.java | 52 +++++-- .../hadoop/hbase/coprocessor/MasterObserver.java | 20 +++ .../org/apache/hadoop/hbase/master/HMaster.java | 70 +++------- .../hadoop/hbase/master/MasterCoprocessorHost.java | 19 +++ .../hadoop/hbase/master/MasterRpcServices.java | 62 +++++++-- .../hadoop/hbase/master/MetaLocationCache.java | 45 ++++-- .../hbase/master/assignment/AssignmentManager.java | 33 ++--- .../hbase/master/assignment/RegionStateStore.java | 44 ++---- .../hadoop/hbase/master/region/MasterRegion.java | 9 ++ .../region/RegionScannerAsResultScanner.java | 88 ++++++++++++ .../hadoop/hbase/master/region/RootStore.java | 153 +++++++++++++++++++++ .../apache/hadoop/hbase/regionserver/HRegion.java | 1 - .../hbase/client/DummyAsyncClusterConnection.java | 5 +- .../hadoop/hbase/client/TestAsyncAdminBase.java | 5 +- .../client/TestFailedMetaReplicaAssigment.java | 10 +- .../hbase/master/TestBackupMasterSyncRoot.java | 113 +++++++++++++++ .../hbase/master/TestCloseAnOpeningRegion.java | 6 +- .../hbase/master/TestClusterRestartFailover.java | 10 +- .../hadoop/hbase/master/TestMetaLocationCache.java | 12 +- .../master/assignment/MockMasterServices.java | 8 +- .../assignment/TestOpenRegionProcedureBackoff.java | 10 +- .../assignment/TestOpenRegionProcedureHang.java | 10 +- .../assignment/TestRaceBetweenSCPAndDTP.java | 10 +- .../assignment/TestRaceBetweenSCPAndTRSP.java | 10 +- .../TestRegionAssignedToMultipleRegionServers.java | 10 +- .../assignment/TestReportOnlineRegionsRace.java | 10 +- ...tReportRegionStateTransitionFromDeadServer.java | 10 +- .../TestReportRegionStateTransitionRetry.java | 10 +- .../master/assignment/TestSCPGetRegionsRace.java | 10 +- .../assignment/TestWakeUpUnexpectedProcedure.java | 10 +- .../apache/hadoop/hbase/util/TestRegionMover2.java | 13 +- 38 files changed, 737 insertions(+), 277 deletions(-) diff --git a/hbase-balancer/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java index 26d8b98..8c609c9 100644 --- a/hbase-balancer/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java +++ b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java @@ -468,8 +468,7 @@ public final class MetaTableAccessor { public static void scanMeta(Connection connection, @Nullable final byte[] startRow, @Nullable final byte[] stopRow, QueryType type, @Nullable Filter filter, int maxRows, final ClientMetaTableAccessor.Visitor visitor) throws IOException { - int rowUpperLimit = maxRows > 0 ? maxRows : Integer.MAX_VALUE; - Scan scan = getMetaScan(connection, rowUpperLimit); + Scan scan = getMetaScan(connection, maxRows); for (byte[] family : type.getFamilies()) { scan.addFamily(family); @@ -486,26 +485,12 @@ public final class MetaTableAccessor { if (LOG.isTraceEnabled()) { LOG.trace("Scanning META" + " starting at row=" + Bytes.toStringBinary(startRow) + - " stopping at row=" + Bytes.toStringBinary(stopRow) + " for max=" + rowUpperLimit + + " stopping at row=" + Bytes.toStringBinary(stopRow) + " for max=" + maxRows + " with caching=" + scan.getCaching()); } - - int currentRow = 0; try (Table metaTable = getMetaHTable(connection)) { try (ResultScanner scanner = metaTable.getScanner(scan)) { - Result data; - while ((data = scanner.next()) != null) { - if (data.isEmpty()) { - continue; - } - // Break if visit returns false. - if (!visitor.visit(data)) { - break; - } - if (++currentRow >= rowUpperLimit) { - break; - } - } + ClientMetaTableAccessor.visit(scanner, visitor, maxRows); } } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/ClientMetaTableAccessor.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/ClientMetaTableAccessor.java index ed0d9b4..f19c913 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/ClientMetaTableAccessor.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/ClientMetaTableAccessor.java @@ -32,6 +32,7 @@ import org.apache.hadoop.hbase.client.Consistency; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.RegionInfo; 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.client.Scan.ReadType; import org.apache.hadoop.hbase.client.TableState; @@ -486,4 +487,26 @@ public final class ClientMetaTableAccessor { } return stopRow; } + + /** + * Visit all the result of the given {@code scanner}. + * <p/> + * It is the caller's duty to close the {@code scanner}. + * @param maxRows maximum rows to visit, or -1 means unlimited. + */ + public static void visit(ResultScanner scanner, Visitor visitor, int maxRows) throws IOException { + for (int rows = 0;;) { + Result result = scanner.next(); + if (result == null) { + return; + } + if (!visitor.visit(result)) { + return; + } + rows++; + if (maxRows > 0 && rows >= maxRows) { + return; + } + } + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java index 8f298e6..4be7546 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java @@ -38,7 +38,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.function.Supplier; -import java.util.stream.Collectors; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellComparator; @@ -53,7 +52,6 @@ import org.apache.hadoop.hbase.client.metrics.ScanMetrics; import org.apache.hadoop.hbase.exceptions.ClientExceptionsUtil; import org.apache.hadoop.hbase.ipc.HBaseRpcController; import org.apache.hadoop.hbase.ipc.RpcClient; -import org.apache.hadoop.hbase.ipc.RpcControllerFactory; import org.apache.hadoop.hbase.ipc.ServerNotRunningYetException; import org.apache.hadoop.hbase.ipc.ServerRpcController; import org.apache.hadoop.hbase.security.User; @@ -77,8 +75,6 @@ import org.apache.hadoop.hbase.shaded.protobuf.ResponseConverter; import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos; import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.ClientService; import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.ScanResponse; -import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ClientMetaService; -import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetAllMetaRegionLocationsRequest; /** * Utility used by client connections. @@ -649,8 +645,8 @@ public final class ConnectionUtils { } } - public static void tryClearMasterStubCache(IOException error, - ClientMetaService.Interface currentStub, AtomicReference<ClientMetaService.Interface> stub) { + public static <T> void tryClearMasterStubCache(IOException error, + T currentStub, AtomicReference<T> stub) { if (ClientExceptionsUtil.isConnectionException(error) || error instanceof ServerNotRunningYetException) { stub.compareAndSet(currentStub, null); @@ -725,35 +721,4 @@ public final class ConnectionUtils { } } } - - public static CompletableFuture<List<HRegionLocation>> getAllMetaRegionLocations( - boolean excludeOfflinedSplitParents, - CompletableFuture<ClientMetaService.Interface> getStubFuture, - AtomicReference<ClientMetaService.Interface> stubRef, - RpcControllerFactory rpcControllerFactory, int callTimeoutMs) { - CompletableFuture<List<HRegionLocation>> future = new CompletableFuture<>(); - addListener(getStubFuture, (stub, error) -> { - if (error != null) { - future.completeExceptionally(error); - return; - } - HBaseRpcController controller = rpcControllerFactory.newController(); - if (callTimeoutMs > 0) { - controller.setCallTimeout(callTimeoutMs); - } - stub.getAllMetaRegionLocations(controller, GetAllMetaRegionLocationsRequest.newBuilder() - .setExcludeOfflinedSplitParents(excludeOfflinedSplitParents).build(), resp -> { - if (controller.failed()) { - IOException ex = controller.getFailed(); - tryClearMasterStubCache(ex, stub, stubRef); - future.completeExceptionally(ex); - return; - } - List<HRegionLocation> locs = resp.getMetaLocationsList().stream() - .map(ProtobufUtil::toRegionLocation).collect(Collectors.toList()); - future.complete(locs); - }); - }); - return future; - } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MasterRegistry.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MasterRegistry.java index d760cf0..d07e133 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MasterRegistry.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/MasterRegistry.java @@ -361,8 +361,12 @@ public class MasterRegistry implements ConnectionRegistry { LocateMetaRegionRequest request = LocateMetaRegionRequest.newBuilder().setRow(ByteString.copyFrom(row)) .setLocateType(ProtobufUtil.toProtoRegionLocateType(locateType)).build(); - return this.<LocateMetaRegionResponse> call((c, s, d) -> s.locateMetaRegion(c, request, d), - r -> true, "locateMeta()").thenApply(this::transformRegionLocations); + return this + .<LocateMetaRegionResponse> call((c, s, d) -> s.locateMetaRegion(c, request, d), + r -> r.getMetaLocationsList().stream() + .anyMatch(l -> l.hasRegionInfo() && l.hasServerName()), + "locateMeta()") + .thenApply(this::transformRegionLocations); } private List<HRegionLocation> @@ -378,7 +382,8 @@ public class MasterRegistry implements ConnectionRegistry { .setExcludeOfflinedSplitParents(excludeOfflinedSplitParents).build(); return this .<GetAllMetaRegionLocationsResponse> call( - (c, s, d) -> s.getAllMetaRegionLocations(c, request, d), r -> true, + (c, s, d) -> s.getAllMetaRegionLocations(c, request, d), + r -> r.getMetaLocationsCount() > 0, "getAllMetaRegionLocations(" + excludeOfflinedSplitParents + ")") .thenApply(this::transformRegionLocationList); } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistry.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistry.java index a10ef18..d66ac1a 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistry.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistry.java @@ -20,6 +20,7 @@ package org.apache.hadoop.hbase.client; import static org.apache.hadoop.hbase.HConstants.DEFAULT_HBASE_RPC_TIMEOUT; import static org.apache.hadoop.hbase.HConstants.HBASE_RPC_READ_TIMEOUT_KEY; import static org.apache.hadoop.hbase.HConstants.HBASE_RPC_TIMEOUT_KEY; +import static org.apache.hadoop.hbase.client.ConnectionUtils.tryClearMasterStubCache; import static org.apache.hadoop.hbase.client.RegionInfo.DEFAULT_REPLICA_ID; import static org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil.lengthOfPBMagic; import static org.apache.hadoop.hbase.util.FutureUtils.addListener; @@ -58,6 +59,7 @@ import org.apache.hbase.thirdparty.com.google.protobuf.ByteString; import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ClientMetaService; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetAllMetaRegionLocationsRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.LocateMetaRegionRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.ZooKeeperProtos; @@ -298,8 +300,27 @@ class ZKConnectionRegistry implements ConnectionRegistry { @Override public CompletableFuture<List<HRegionLocation>> getAllMetaRegionLocations(boolean excludeOfflinedSplitParents) { - return ConnectionUtils.getAllMetaRegionLocations(excludeOfflinedSplitParents, getStub(), - cachedStub, rpcControllerFactory, -1); + CompletableFuture<List<HRegionLocation>> future = new CompletableFuture<>(); + addListener(getStub(), (stub, error) -> { + if (error != null) { + future.completeExceptionally(error); + return; + } + HBaseRpcController controller = rpcControllerFactory.newController(); + stub.getAllMetaRegionLocations(controller, GetAllMetaRegionLocationsRequest.newBuilder() + .setExcludeOfflinedSplitParents(excludeOfflinedSplitParents).build(), resp -> { + if (controller.failed()) { + IOException ex = controller.getFailed(); + tryClearMasterStubCache(ex, stub, cachedStub); + future.completeExceptionally(ex); + return; + } + List<HRegionLocation> locs = resp.getMetaLocationsList().stream() + .map(ProtobufUtil::toRegionLocation).collect(Collectors.toList()); + future.complete(locs); + }); + }); + return future; } @Override diff --git a/hbase-protocol-shaded/src/main/protobuf/server/master/Master.proto b/hbase-protocol-shaded/src/main/protobuf/server/master/Master.proto index 01a8941..2bb35c2 100644 --- a/hbase-protocol-shaded/src/main/protobuf/server/master/Master.proto +++ b/hbase-protocol-shaded/src/main/protobuf/server/master/Master.proto @@ -1371,3 +1371,17 @@ service ClientMetaService { rpc GetAllMetaRegionLocations(GetAllMetaRegionLocationsRequest) returns(GetAllMetaRegionLocationsResponse); } + +message SyncRootRequest { + required int64 lastSyncSeqId = 1; +} + +message SyncRootResponse { + required int64 lastModifiedSeqId = 1; + repeated RegionLocation meta_locations = 2; +} + +service RootSyncService { + rpc SyncRoot(SyncRootRequest) + returns(SyncRootResponse); +} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/AsyncClusterConnection.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/AsyncClusterConnection.java index 8e64b4b..8b0f0a2 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/AsyncClusterConnection.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/AsyncClusterConnection.java @@ -103,5 +103,6 @@ public interface AsyncClusterConnection extends AsyncConnection { /** * Fetch all meta region locations from active master, used by backup masters for caching. */ - CompletableFuture<List<HRegionLocation>> getAllMetaRegionLocations(int callTimeoutMs); + CompletableFuture<Pair<Long, List<HRegionLocation>>> syncRoot(long lastSyncSeqId, + int callTimeoutMs); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/AsyncClusterConnectionImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/AsyncClusterConnectionImpl.java index cfe62db..8fdd439 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/client/AsyncClusterConnectionImpl.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/client/AsyncClusterConnectionImpl.java @@ -17,17 +17,23 @@ */ package org.apache.hadoop.hbase.client; +import static org.apache.hadoop.hbase.client.ConnectionUtils.tryClearMasterStubCache; +import static org.apache.hadoop.hbase.util.FutureUtils.addListener; + +import java.io.IOException; import java.net.SocketAddress; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionLocation; import org.apache.hadoop.hbase.RegionLocations; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.ipc.HBaseRpcController; import org.apache.hadoop.hbase.ipc.RpcClient; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.util.Pair; @@ -46,7 +52,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.PrepareBul import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.PrepareBulkLoadResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier; import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType; -import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ClientMetaService; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RootSyncService; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SyncRootRequest; /** * The implementation of AsyncClusterConnection. @@ -54,11 +61,11 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ClientMeta @InterfaceAudience.Private class AsyncClusterConnectionImpl extends AsyncConnectionImpl implements AsyncClusterConnection { - private final AtomicReference<ClientMetaService.Interface> cachedClientMetaStub = + private final AtomicReference<RootSyncService.Interface> cachedRootSyncStub = new AtomicReference<>(); - private final AtomicReference<CompletableFuture<ClientMetaService.Interface>> - clientMetaStubMakeFuture = new AtomicReference<>(); + private final AtomicReference<CompletableFuture<RootSyncService.Interface>> + rootSyncStubMakeFuture = new AtomicReference<>(); public AsyncClusterConnectionImpl(Configuration conf, ConnectionRegistry registry, String clusterId, SocketAddress localAddress, User user) { @@ -143,15 +150,38 @@ class AsyncClusterConnectionImpl extends AsyncConnectionImpl implements AsyncClu .call(); } - private CompletableFuture<ClientMetaService.Interface> getClientMetaStub() { - return ConnectionUtils.getMasterStub(registry, cachedClientMetaStub, clientMetaStubMakeFuture, - rpcClient, user, rpcTimeout, TimeUnit.MILLISECONDS, ClientMetaService::newStub, - "ClientMetaService"); + private CompletableFuture<RootSyncService.Interface> getRootSyncStub() { + return ConnectionUtils.getMasterStub(registry, cachedRootSyncStub, rootSyncStubMakeFuture, + rpcClient, user, rpcTimeout, TimeUnit.MILLISECONDS, RootSyncService::newStub, + "RootSyncService"); } @Override - public CompletableFuture<List<HRegionLocation>> getAllMetaRegionLocations(int callTimeoutMs) { - return ConnectionUtils.getAllMetaRegionLocations(false, getClientMetaStub(), - cachedClientMetaStub, rpcControllerFactory, callTimeoutMs); + public CompletableFuture<Pair<Long, List<HRegionLocation>>> syncRoot(long lastSyncSeqId, + int callTimeoutMs) { + CompletableFuture<Pair<Long, List<HRegionLocation>>> future = new CompletableFuture<>(); + addListener(getRootSyncStub(), (stub, error) -> { + if (error != null) { + future.completeExceptionally(error); + return; + } + HBaseRpcController controller = rpcControllerFactory.newController(); + if (callTimeoutMs > 0) { + controller.setCallTimeout(callTimeoutMs); + } + stub.syncRoot(controller, + SyncRootRequest.newBuilder().setLastSyncSeqId(lastSyncSeqId).build(), resp -> { + if (controller.failed()) { + IOException ex = controller.getFailed(); + tryClearMasterStubCache(ex, stub, cachedRootSyncStub); + future.completeExceptionally(ex); + return; + } + List<HRegionLocation> locs = resp.getMetaLocationsList().stream() + .map(ProtobufUtil::toRegionLocation).collect(Collectors.toList()); + future.complete(Pair.newPair(resp.getLastModifiedSeqId(), locs)); + }); + }); + return future; } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java index 8ca8972..e6197ba 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java @@ -1824,4 +1824,24 @@ public interface MasterObserver { default void postGetAllMetaRegionLocations(ObserverContext<MasterCoprocessorEnvironment> ctx, boolean excludeOfflinedSplitParents, List<HRegionLocation> locs) { } + + /** + * Called before syncing root + * @param ctx ctx the coprocessor instance's environment + * @param lastSyncSeqId the sequence id when we call sync root last time + */ + default void preSyncRoot(ObserverContext<MasterCoprocessorEnvironment> ctx, long lastSyncSeqId) { + } + + /** + * Called before syncing root + * @param ctx ctx the coprocessor instance's environment + * @param lastSyncSeqId the sequence id when we call sync root last time + * @param lastModifiedSeqId the sequence id for this sync operation, it could be less than or + * equal to {@code lastSyncSeqId}, then it usually means we do not sync anything. + * @param locs the locations of all meta regions, including meta replicas if any. + */ + default void postSyncRoot(ObserverContext<MasterCoprocessorEnvironment> ctx, long lastSyncSeqId, + long lastModifiedSeqId, List<HRegionLocation> locs) { + } } 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 793a473..966d3fb 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 @@ -96,6 +96,7 @@ import org.apache.hadoop.hbase.client.RegionLocateType; import org.apache.hadoop.hbase.client.RegionReplicaUtil; import org.apache.hadoop.hbase.client.RegionStatesCount; 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.client.TableDescriptor; import org.apache.hadoop.hbase.client.TableDescriptorBuilder; @@ -150,6 +151,7 @@ import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure; import org.apache.hadoop.hbase.master.procedure.TruncateTableProcedure; import org.apache.hadoop.hbase.master.region.MasterRegion; import org.apache.hadoop.hbase.master.region.MasterRegionFactory; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.master.replication.AbstractPeerProcedure; import org.apache.hadoop.hbase.master.replication.AddPeerProcedure; import org.apache.hadoop.hbase.master.replication.DisablePeerProcedure; @@ -470,7 +472,11 @@ public class HMaster extends HRegionServer implements MasterServices { private ProcedureStore procedureStore; // the master local storage to store procedure data, root table, etc. - private MasterRegion masterRegion; + @VisibleForTesting + MasterRegion masterRegion; + + // a wrapper of MasterRegion to provide root table storage + private RootStore rootStore; // handle table states private TableStateManager tableStateManager; @@ -902,8 +908,8 @@ public class HMaster extends HRegionServer implements MasterServices { // Will be overriden in test to inject customized AssignmentManager @VisibleForTesting protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManager(master, masterRegion); + RootStore rootStore) { + return new AssignmentManager(master, rootStore); } /** @@ -1066,6 +1072,7 @@ public class HMaster extends HRegionServer implements MasterServices { // initialize master local region masterRegion = MasterRegionFactory.create(this); + rootStore = new RootStore(masterRegion); tryMigrateRootTableFromZooKeeper(); @@ -1079,7 +1086,7 @@ public class HMaster extends HRegionServer implements MasterServices { .collect(Collectors.groupingBy(p -> p.getClass())); // Create Assignment Manager - this.assignmentManager = createAssignmentManager(this, masterRegion); + this.assignmentManager = createAssignmentManager(this, rootStore); this.assignmentManager.start(); // TODO: TRSP can perform as the sub procedure for other procedures, so even if it is marked as // completed, it could still be in the procedure list. This is a bit strange but is another @@ -4005,16 +4012,12 @@ public class HMaster extends HRegionServer implements MasterServices { } Scan scan = CatalogFamilyFormat.createRegionLocateScan(TableName.META_TABLE_NAME, row, locateType, 1); - try (RegionScanner scanner = masterRegion.getScanner(scan)) { - boolean moreRows; - List<Cell> cells = new ArrayList<>(); - do { - moreRows = scanner.next(cells); - if (cells.isEmpty()) { - continue; + try (ResultScanner scanner = rootStore.getScanner(scan)) { + for (;;) { + Result result = scanner.next(); + if (result == null) { + break; } - Result result = Result.create(cells); - cells.clear(); RegionLocations locs = CatalogFamilyFormat.getRegionLocations(result); if (locs == null || locs.getDefaultRegionLocation() == null) { LOG.warn("No location found when locating meta region with row='{}', locateType={}", @@ -4032,7 +4035,7 @@ public class HMaster extends HRegionServer implements MasterServices { continue; } return locs; - } while (moreRows); + } LOG.warn("No location available when locating meta region with row='{}', locateType={}", Bytes.toStringBinary(row), locateType); return null; @@ -4041,39 +4044,10 @@ public class HMaster extends HRegionServer implements MasterServices { public List<RegionLocations> getAllMetaRegionLocations(boolean excludeOfflinedSplitParents) throws IOException { - Scan scan = new Scan().addFamily(HConstants.CATALOG_FAMILY); - List<RegionLocations> list = new ArrayList<>(); - try (RegionScanner scanner = masterRegion.getScanner(scan)) { - boolean moreRows; - List<Cell> cells = new ArrayList<>(); - do { - moreRows = scanner.next(cells); - if (cells.isEmpty()) { - continue; - } - Result result = Result.create(cells); - cells.clear(); - RegionLocations locs = CatalogFamilyFormat.getRegionLocations(result); - if (locs == null) { - LOG.warn("No locations in {}", result); - continue; - } - HRegionLocation loc = locs.getRegionLocation(); - if (loc == null) { - LOG.warn("No non null location in {}", result); - continue; - } - RegionInfo info = loc.getRegion(); - if (info == null) { - LOG.warn("No serialized RegionInfo in {}", result); - continue; - } - if (excludeOfflinedSplitParents && info.isSplitParent()) { - continue; - } - list.add(locs); - } while (moreRows); - } - return list; + return rootStore.getAllMetaRegionLocations(excludeOfflinedSplitParents); + } + + public Pair<Long, List<RegionLocations>> syncRoot(long lastSyncSeqId) throws IOException { + return rootStore.sync(lastSyncSeqId); } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java index 728da5c..3289c9d 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java @@ -2078,4 +2078,23 @@ public class MasterCoprocessorHost } }); } + + public void preSyncRoot(long lastSyncSeqId) throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + observer.preSyncRoot(this, lastSyncSeqId); + } + }); + } + + public void postSyncRoot(long lastSyncSeqId, long lastModifiedSeqId, List<HRegionLocation> locs) + throws IOException { + execOperation(coprocEnvironments.isEmpty() ? null : new MasterObserverOperation() { + @Override + public void call(MasterObserver observer) throws IOException { + observer.postSyncRoot(this, lastSyncSeqId, lastModifiedSeqId, locs); + } + }); + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java index fbda246..0593df9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java @@ -293,6 +293,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.Recommissi import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RegionSpecifierAndState; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RestoreSnapshotRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RestoreSnapshotResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RootSyncService; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCatalogScanRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCatalogScanResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.RunCleanerChoreRequest; @@ -328,6 +329,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SwitchExce import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SwitchExceedThrottleQuotaResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SwitchRpcThrottleRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SwitchRpcThrottleResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SyncRootRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SyncRootResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.TruncateTableRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.TruncateTableResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.UnassignRegionRequest; @@ -410,9 +413,10 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.VisibilityLabelsProtos. */ @InterfaceAudience.Private @SuppressWarnings("deprecation") -public class MasterRpcServices extends RSRpcServices implements MasterService.BlockingInterface, - RegionServerStatusService.BlockingInterface, LockService.BlockingInterface, - HbckService.BlockingInterface, ClientMetaService.BlockingInterface { +public class MasterRpcServices extends RSRpcServices + implements MasterService.BlockingInterface, RegionServerStatusService.BlockingInterface, + LockService.BlockingInterface, HbckService.BlockingInterface, ClientMetaService.BlockingInterface, + RootSyncService.BlockingInterface { private static final Logger LOG = LoggerFactory.getLogger(MasterRpcServices.class.getName()); private static final Logger AUDITLOG = @@ -546,7 +550,7 @@ public class MasterRpcServices extends RSRpcServices implements MasterService.Bl */ @Override protected List<BlockingServiceAndInterface> getServices() { - List<BlockingServiceAndInterface> bssi = new ArrayList<>(5); + List<BlockingServiceAndInterface> bssi = new ArrayList<>(); bssi.add(new BlockingServiceAndInterface(MasterService.newReflectiveBlockingService(this), MasterService.BlockingInterface.class)); bssi.add( @@ -558,6 +562,8 @@ public class MasterRpcServices extends RSRpcServices implements MasterService.Bl HbckService.BlockingInterface.class)); bssi.add(new BlockingServiceAndInterface(ClientMetaService.newReflectiveBlockingService(this), ClientMetaService.BlockingInterface.class)); + bssi.add(new BlockingServiceAndInterface(RootSyncService.newReflectiveBlockingService(this), + RootSyncService.BlockingInterface.class)); bssi.addAll(super.getServices()); return bssi; } @@ -3417,6 +3423,18 @@ public class MasterRpcServices extends RSRpcServices implements MasterService.Bl } } + private static List<HRegionLocation> locs2Loc(List<RegionLocations> locs) { + List<HRegionLocation> list = new ArrayList<>(); + for (RegionLocations ls : locs) { + for (HRegionLocation loc : ls) { + if (loc != null) { + list.add(loc); + } + } + } + return list; + } + @Override public GetAllMetaRegionLocationsResponse getAllMetaRegionLocations(RpcController controller, GetAllMetaRegionLocationsRequest request) throws ServiceException { @@ -3431,16 +3449,7 @@ public class MasterRpcServices extends RSRpcServices implements MasterService.Bl list = cache.getAllMetaRegionLocations(excludeOfflinedSplitParents); } else { List<RegionLocations> locs = master.getAllMetaRegionLocations(excludeOfflinedSplitParents); - list = new ArrayList<>(); - if (locs != null) { - for (RegionLocations ls : locs) { - for (HRegionLocation loc : ls) { - if (loc != null) { - list.add(loc); - } - } - } - } + list = locs2Loc(locs); } GetAllMetaRegionLocationsResponse.Builder builder = GetAllMetaRegionLocationsResponse.newBuilder(); @@ -3456,4 +3465,29 @@ public class MasterRpcServices extends RSRpcServices implements MasterService.Bl throw new ServiceException(e); } } + + @Override + public SyncRootResponse syncRoot(RpcController controller, SyncRootRequest request) + throws ServiceException { + long lastSyncSeqId = request.getLastSyncSeqId(); + try { + master.checkServiceStarted(); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preSyncRoot(lastSyncSeqId); + } + Pair<Long, List<RegionLocations>> pair = master.syncRoot(lastSyncSeqId); + List<HRegionLocation> locs = locs2Loc(pair.getSecond()); + SyncRootResponse.Builder builder = SyncRootResponse.newBuilder(); + builder.setLastModifiedSeqId(pair.getFirst()); + for (HRegionLocation loc : locs) { + builder.addMetaLocations(ProtobufUtil.toRegionLocation(loc)); + } + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postSyncRoot(lastSyncSeqId, pair.getFirst(), locs); + } + return builder.build(); + } catch (IOException e) { + throw new ServiceException(e); + } + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaLocationCache.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaLocationCache.java index 0f5cf11..cc234f6 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaLocationCache.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaLocationCache.java @@ -30,7 +30,9 @@ import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; +import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionLocation; import org.apache.hadoop.hbase.MetaCellComparator; import org.apache.hadoop.hbase.RegionLocations; @@ -50,7 +52,7 @@ import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesti * A cache of meta region locations. */ @InterfaceAudience.Private -class MetaLocationCache implements Stoppable { +public class MetaLocationCache implements Stoppable { private static final Logger LOG = LoggerFactory.getLogger(MetaLocationCache.class); @@ -68,13 +70,17 @@ class MetaLocationCache implements Stoppable { // default timeout 1 second private static final int DEFAULT_FETCH_TIMEOUT_MS = 1000; - private static final class CacheHolder { + @VisibleForTesting + static final class CacheHolder { + + final long lastSyncSeqId; final NavigableMap<byte[], RegionLocations> cache; final List<HRegionLocation> all; - CacheHolder(List<HRegionLocation> all) { + CacheHolder(long lastSyncSeqId, List<HRegionLocation> all) { + this.lastSyncSeqId = lastSyncSeqId; this.all = Collections.unmodifiableList(all); NavigableMap<byte[], SortedSet<HRegionLocation>> startKeyToLocs = new TreeMap<>(MetaCellComparator.ROW_COMPARATOR); @@ -93,7 +99,10 @@ class MetaLocationCache implements Stoppable { } } - private volatile CacheHolder holder; + @VisibleForTesting + final AtomicReference<CacheHolder> holder = new AtomicReference<>(); + + private final ScheduledChore refreshChore; private volatile boolean stopped = false; @@ -102,34 +111,43 @@ class MetaLocationCache implements Stoppable { master.getConfiguration().getInt(SYNC_INTERVAL_SECONDS, DEFAULT_SYNC_INTERVAL_SECONDS); int fetchTimeoutMs = master.getConfiguration().getInt(FETCH_TIMEOUT_MS, DEFAULT_FETCH_TIMEOUT_MS); - master.getChoreService().scheduleChore(new ScheduledChore( - getClass().getSimpleName() + "-Sync-Chore", this, syncIntervalSeconds, 0, TimeUnit.SECONDS) { + refreshChore = new ScheduledChore(getClass().getSimpleName() + "-Sync-Chore", this, + syncIntervalSeconds, 0, TimeUnit.SECONDS) { @Override protected void chore() { AsyncClusterConnection conn = master.getAsyncClusterConnection(); if (conn != null) { - addListener(conn.getAllMetaRegionLocations(fetchTimeoutMs), (locs, error) -> { + final CacheHolder ch = holder.get(); + long lastSyncSeqId = ch != null ? ch.lastSyncSeqId : HConstants.NO_SEQNUM; + addListener(conn.syncRoot(lastSyncSeqId, fetchTimeoutMs), (resp, error) -> { if (error != null) { - LOG.warn("Failed to fetch all meta region locations from active master", error); + LOG.warn("Failed to sync root data from active master", error); return; } - holder = new CacheHolder(locs); + long lastModifiedSeqId = resp.getFirst().longValue(); + if (ch == null || lastModifiedSeqId > ch.lastSyncSeqId && holder.get() == ch) { + // since we may trigger cache refresh when locating, here we use CAS to avoid race + holder.compareAndSet(ch, new CacheHolder(lastModifiedSeqId, resp.getSecond())); + } }); } } - }); + }; + master.getChoreService().scheduleChore(refreshChore); } - RegionLocations locateMeta(byte[] row, RegionLocateType locateType) { + @VisibleForTesting + public RegionLocations locateMeta(byte[] row, RegionLocateType locateType) { if (locateType == RegionLocateType.AFTER) { // as we know the exact row after us, so we can just create the new row, and use the same // algorithm to locate it. row = Arrays.copyOf(row, row.length + 1); locateType = RegionLocateType.CURRENT; } - CacheHolder holder = this.holder; + CacheHolder holder = this.holder.get(); if (holder == null) { + refreshChore.triggerNow(); return null; } return locateType.equals(RegionLocateType.BEFORE) ? @@ -138,8 +156,9 @@ class MetaLocationCache implements Stoppable { } List<HRegionLocation> getAllMetaRegionLocations(boolean excludeOfflinedSplitParents) { - CacheHolder holder = this.holder; + CacheHolder holder = this.holder.get(); if (holder == null) { + refreshChore.triggerNow(); return Collections.emptyList(); } if (!excludeOfflinedSplitParents) { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java index fc621ff..8d789c2 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/AssignmentManager.java @@ -34,7 +34,6 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.CatalogFamilyFormat; -import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.DoNotRetryIOException; import org.apache.hadoop.hbase.HBaseIOException; import org.apache.hadoop.hbase.HConstants; @@ -47,6 +46,7 @@ import org.apache.hadoop.hbase.client.MasterSwitchType; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionStatesCount; 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.client.TableDescriptor; import org.apache.hadoop.hbase.client.TableState; @@ -67,13 +67,12 @@ import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.master.procedure.MasterProcedureScheduler; import org.apache.hadoop.hbase.master.procedure.ProcedureSyncWait; import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.procedure2.Procedure; import org.apache.hadoop.hbase.procedure2.ProcedureEvent; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.procedure2.ProcedureInMemoryChore; import org.apache.hadoop.hbase.procedure2.util.StringUtils; -import org.apache.hadoop.hbase.regionserver.RegionScanner; import org.apache.hadoop.hbase.regionserver.SequenceId; import org.apache.hadoop.hbase.rsgroup.RSGroupBasedLoadBalancer; import org.apache.hadoop.hbase.util.Bytes; @@ -172,22 +171,22 @@ public class AssignmentManager { private final int assignMaxAttempts; private final int assignRetryImmediatelyMaxAttempts; - private final MasterRegion masterRegion; + private final RootStore rootStore; private final Object checkIfShouldMoveSystemRegionLock = new Object(); private Thread assignThread; - public AssignmentManager(MasterServices master, MasterRegion masterRegion) { - this(master, masterRegion, new RegionStateStore(master, masterRegion)); + public AssignmentManager(MasterServices master, RootStore rootStore) { + this(master, rootStore, new RegionStateStore(master, rootStore)); } @VisibleForTesting - AssignmentManager(MasterServices master, MasterRegion masterRegion, RegionStateStore stateStore) { + AssignmentManager(MasterServices master, RootStore rootStore, RegionStateStore stateStore) { this.master = master; this.regionStateStore = stateStore; this.metrics = new MetricsAssignmentManager(); - this.masterRegion = masterRegion; + this.rootStore = rootStore; final Configuration conf = master.getConfiguration(); @@ -231,17 +230,13 @@ public class AssignmentManager { // load meta region states. // notice that, here we will load all replicas, and in MasterMetaBootstrap we may assign new // replicas, or remove excess replicas. - try (RegionScanner scanner = - masterRegion.getScanner(new Scan().addFamily(HConstants.CATALOG_FAMILY))) { - List<Cell> cells = new ArrayList<>(); - boolean moreRows; - do { - moreRows = scanner.next(cells); - if (cells.isEmpty()) { - continue; + try (ResultScanner scanner = + rootStore.getScanner(new Scan().addFamily(HConstants.CATALOG_FAMILY))) { + for(;;) { + Result result = scanner.next(); + if (result == null) { + break; } - Result result = Result.create(cells); - cells.clear(); RegionStateStore .visitMetaEntry((r, regionInfo, state, regionLocation, lastHost, openSeqNum) -> { RegionStateNode regionNode = regionStates.getOrCreateRegionStateNode(regionInfo); @@ -265,7 +260,7 @@ public class AssignmentManager { } } }, result); - } while (moreRows); + } } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java index 4e7d271..5fe93f9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java @@ -48,6 +48,7 @@ import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionInfoBuilder; import org.apache.hadoop.hbase.client.RegionReplicaUtil; 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.client.Table; import org.apache.hadoop.hbase.client.TableDescriptor; @@ -55,10 +56,9 @@ import org.apache.hadoop.hbase.master.MasterFileSystem; import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.master.RegionState; import org.apache.hadoop.hbase.master.RegionState.State; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.procedure2.Procedure; import org.apache.hadoop.hbase.procedure2.util.StringUtils; -import org.apache.hadoop.hbase.regionserver.RegionScanner; import org.apache.hadoop.hbase.replication.ReplicationBarrierFamilyFormat; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; @@ -92,11 +92,11 @@ public class RegionStateStore { private final MasterServices master; - private final MasterRegion masterRegion; + private final RootStore rootStore; - public RegionStateStore(MasterServices master, MasterRegion masterRegion) { + public RegionStateStore(MasterServices master, RootStore rootStore) { this.master = master; - this.masterRegion = masterRegion; + this.rootStore = rootStore; } @FunctionalInterface @@ -238,21 +238,9 @@ public class RegionStateStore { // scan meta first MetaTableAccessor.fullScanRegions(master.getConnection(), visitor); // scan root - try (RegionScanner scanner = - masterRegion.getScanner(new Scan().addFamily(HConstants.CATALOG_FAMILY))) { - boolean moreRows; - List<Cell> cells = new ArrayList<>(); - do { - moreRows = scanner.next(cells); - if (cells.isEmpty()) { - continue; - } - Result result = Result.create(cells); - cells.clear(); - if (!visitor.visit(result)) { - break; - } - } while (moreRows); + try (ResultScanner scanner = + rootStore.getScanner(new Scan().addFamily(HConstants.CATALOG_FAMILY))) { + ClientMetaTableAccessor.visit(scanner, visitor, -1); } } @@ -270,7 +258,7 @@ public class RegionStateStore { throws IOException { try { if (regionInfo.isMetaRegion()) { - masterRegion.update(r -> r.put(put)); + rootStore.put(put); } else { try (Table table = master.getConnection().getTable(TableName.META_TABLE_NAME)) { table.put(put); @@ -301,11 +289,7 @@ public class RegionStateStore { private void multiMutate(RegionInfo ri, List<Mutation> mutations) throws IOException { debugLogMutations(mutations); if (ri.isMetaRegion()) { - masterRegion.update(region -> { - List<byte[]> rowsToLock = - mutations.stream().map(Mutation::getRow).collect(Collectors.toList()); - region.mutateRowsWithLocks(mutations, rowsToLock, HConstants.NO_NONCE, HConstants.NO_NONCE); - }); + rootStore.multiMutate(mutations); } else { byte[] row = Bytes.toBytes(RegionReplicaUtil.getRegionInfoForDefaultReplica(ri).getRegionNameAsString() + @@ -342,7 +326,7 @@ public class RegionStateStore { Get get = new Get(CatalogFamilyFormat.getMetaKeyForRegion(region)).addFamily(HConstants.CATALOG_FAMILY); if (region.isMetaRegion()) { - return masterRegion.get(get); + return rootStore.get(get); } else { try (Table table = getMetaTable()) { return table.get(get); @@ -505,7 +489,7 @@ public class RegionStateStore { } debugLogMutation(delete); if (mergeRegion.isMetaRegion()) { - masterRegion.update(r -> r.delete(delete)); + rootStore.delete(delete); } else { try (Table table = getMetaTable()) { table.delete(delete); @@ -576,9 +560,7 @@ public class RegionStateStore { if (!metaRegions.isEmpty()) { List<Delete> deletes = makeDeleteRegionInfos(metaRegions, ts); debugLogMutations(deletes); - for (Delete d : deletes) { - masterRegion.update(r -> r.delete(d)); - } + rootStore.delete(deletes); LOG.info("Deleted {} regions from ROOT", metaRegions.size()); LOG.debug("Deleted regions: {}", metaRegions); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/MasterRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/MasterRegion.java index cbfc2a3..5bc23c9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/MasterRegion.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/MasterRegion.java @@ -142,6 +142,15 @@ public final class MasterRegion { return region.getScanner(scan); } + WAL getWAL() { + return region.getWAL(); + } + + @VisibleForTesting + public long getReadPoint() { + return region.getMVCC().getReadPoint(); + } + @VisibleForTesting public FlushResult flush(boolean force) throws IOException { return region.flush(force); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/RegionScannerAsResultScanner.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/RegionScannerAsResultScanner.java new file mode 100644 index 0000000..f7ac315 --- /dev/null +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/RegionScannerAsResultScanner.java @@ -0,0 +1,88 @@ +/** + * 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.region; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.apache.hadoop.hbase.Cell; +import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.client.ResultScanner; +import org.apache.hadoop.hbase.client.metrics.ScanMetrics; +import org.apache.hadoop.hbase.regionserver.RegionScanner; +import org.apache.yetus.audience.InterfaceAudience; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Wrap a {@link RegionScanner} as a {@link ResultScanner}. + */ +@InterfaceAudience.Private +class RegionScannerAsResultScanner implements ResultScanner { + + private static final Logger LOG = LoggerFactory.getLogger(RootStore.class); + + private final RegionScanner scanner; + + private boolean moreRows = true; + + private final List<Cell> cells = new ArrayList<>(); + + public RegionScannerAsResultScanner(RegionScanner scanner) { + this.scanner = scanner; + } + + @Override + public boolean renewLease() { + return true; + } + + @Override + public Result next() throws IOException { + if (!moreRows) { + return null; + } + for (;;) { + moreRows = scanner.next(cells); + if (cells.isEmpty()) { + if (!moreRows) { + return null; + } else { + continue; + } + } + Result result = Result.create(cells); + cells.clear(); + return result; + } + } + + @Override + public ScanMetrics getScanMetrics() { + return null; + } + + @Override + public void close() { + try { + scanner.close(); + } catch (IOException e) { + LOG.warn("Failed to close scanner", e); + } + } +} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/RootStore.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/RootStore.java new file mode 100644 index 0000000..0607f9e --- /dev/null +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/region/RootStore.java @@ -0,0 +1,153 @@ +/** + * 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.region; + +import static org.apache.hadoop.hbase.HConstants.NO_NONCE; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; +import org.apache.hadoop.hbase.CatalogFamilyFormat; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.HRegionLocation; +import org.apache.hadoop.hbase.RegionLocations; +import org.apache.hadoop.hbase.client.Delete; +import org.apache.hadoop.hbase.client.Get; +import org.apache.hadoop.hbase.client.Mutation; +import org.apache.hadoop.hbase.client.Put; +import org.apache.hadoop.hbase.client.RegionInfo; +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.regionserver.wal.WALActionsListener; +import org.apache.hadoop.hbase.util.AtomicUtils; +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.util.Pair; +import org.apache.hadoop.hbase.wal.WALEdit; +import org.apache.hadoop.hbase.wal.WALKey; +import org.apache.yetus.audience.InterfaceAudience; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A wrapper of {@link MasterRegion} to support root table storage. + */ +@InterfaceAudience.Private +public class RootStore { + + private static final Logger LOG = LoggerFactory.getLogger(RootStore.class); + + private final MasterRegion region; + + private final AtomicLong lastModifiedSeqId = new AtomicLong(HConstants.NO_SEQNUM); + + public RootStore(MasterRegion region) { + this.region = region; + lastModifiedSeqId.set(region.getReadPoint()); + region.getWAL().registerWALActionsListener(new WALActionsListener() { + + @Override + public void postAppend(long entryLen, long elapsedTimeMillis, WALKey logKey, WALEdit logEdit) + throws IOException { + for (byte[] family : logEdit.getFamilies()) { + // we only care about catalog family + if (!Bytes.equals(family, HConstants.CATALOG_FAMILY)) { + return; + } + } + AtomicUtils.updateMax(lastModifiedSeqId, logKey.getSequenceId()); + } + }); + } + + public ResultScanner getScanner(Scan scan) throws IOException { + return new RegionScannerAsResultScanner(region.getScanner(scan)); + } + + public Result get(Get get) throws IOException { + return region.get(get); + } + + public void put(Put put) throws IOException { + region.update(r -> r.put(put)); + } + + public void delete(Delete delete) throws IOException { + region.update(r -> r.delete(delete)); + } + + public void delete(List<Delete> deletes) throws IOException { + region.update(r -> { + for (Delete delete : deletes) { + r.delete(delete); + } + }); + } + + public void multiMutate(List<Mutation> mutations) throws IOException { + region.update(r -> { + List<byte[]> rowsToLock = + mutations.stream().map(Mutation::getRow).collect(Collectors.toList()); + r.mutateRowsWithLocks(mutations, rowsToLock, NO_NONCE, NO_NONCE); + }); + } + + public List<RegionLocations> getAllMetaRegionLocations(boolean excludeOfflinedSplitParents) + throws IOException { + List<RegionLocations> list = new ArrayList<>(); + try (ResultScanner scanner = getScanner(new Scan().addFamily(HConstants.CATALOG_FAMILY))) { + for (;;) { + Result result = scanner.next(); + if (result == null) { + break; + } + RegionLocations locs = CatalogFamilyFormat.getRegionLocations(result); + if (locs == null) { + LOG.warn("No locations in {}", result); + continue; + } + HRegionLocation loc = locs.getRegionLocation(); + if (loc == null) { + LOG.warn("No non null location in {}", result); + continue; + } + RegionInfo info = loc.getRegion(); + if (info == null) { + LOG.warn("No serialized RegionInfo in {}", result); + continue; + } + if (excludeOfflinedSplitParents && info.isSplitParent()) { + continue; + } + list.add(locs); + } + } + return list; + } + + public Pair<Long, List<RegionLocations>> sync(long lastSyncSeqId) throws IOException { + long lastModSeqId = Math.min(lastModifiedSeqId.get(), region.getReadPoint()); + if (lastModSeqId <= lastSyncSeqId) { + return Pair.newPair(lastSyncSeqId, Collections.emptyList()); + } + return Pair.newPair(lastModSeqId, getAllMetaRegionLocations(false)); + } +} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java index e638a8d..923382c 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java @@ -1518,7 +1518,6 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi } } - @VisibleForTesting public MultiVersionConcurrencyControl getMVCC() { return mvcc; } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/DummyAsyncClusterConnection.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/DummyAsyncClusterConnection.java index 4385a5a..93e8aa5 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/DummyAsyncClusterConnection.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/DummyAsyncClusterConnection.java @@ -155,12 +155,13 @@ public class DummyAsyncClusterConnection implements AsyncClusterConnection { } @Override - public Connection toConnection() { + public CompletableFuture<Pair<Long, List<HRegionLocation>>> syncRoot(long lastSyncSeqId, + int callTimeoutMs) { return null; } @Override - public CompletableFuture<List<HRegionLocation>> getAllMetaRegionLocations(int callTimeoutMs) { + public Connection toConnection() { return null; } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdminBase.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdminBase.java index 70cffd8..e895f16 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdminBase.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdminBase.java @@ -26,7 +26,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ForkJoinPool; import java.util.function.Supplier; import java.util.regex.Pattern; -import org.apache.commons.io.IOUtils; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.StartMiniClusterOption; @@ -43,6 +42,8 @@ import org.junit.runners.Parameterized.Parameters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.apache.hbase.thirdparty.com.google.common.io.Closeables; + /** * Class to test AsyncAdmin. */ @@ -92,7 +93,7 @@ public abstract class TestAsyncAdminBase extends AbstractTestUpdateConfiguration @AfterClass public static void tearDownAfterClass() throws Exception { - IOUtils.closeQuietly(ASYNC_CONN); + Closeables.close(ASYNC_CONN, true); TEST_UTIL.shutdownMiniCluster(); } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFailedMetaReplicaAssigment.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFailedMetaReplicaAssigment.java index d242932..1fd8b96 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFailedMetaReplicaAssigment.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestFailedMetaReplicaAssigment.java @@ -35,7 +35,7 @@ import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.master.assignment.AssignmentManager; import org.apache.hadoop.hbase.master.assignment.RegionStateNode; import org.apache.hadoop.hbase.master.assignment.TransitRegionStateProcedure; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.testclassification.MediumTests; import org.apache.hadoop.hbase.testclassification.MiscTests; import org.junit.AfterClass; @@ -113,8 +113,8 @@ public class TestFailedMetaReplicaAssigment { @Override public AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new BrokenMasterMetaAssignmentManager(master, masterRegion); + RootStore rootStore) { + return new BrokenMasterMetaAssignmentManager(master, rootStore); } } @@ -122,8 +122,8 @@ public class TestFailedMetaReplicaAssigment { MasterServices master; public BrokenMasterMetaAssignmentManager(final MasterServices master, - MasterRegion masterRegion) { - super(master, masterRegion); + RootStore rootStore) { + super(master, rootStore); this.master = master; } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestBackupMasterSyncRoot.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestBackupMasterSyncRoot.java new file mode 100644 index 0000000..be85bd8 --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestBackupMasterSyncRoot.java @@ -0,0 +1,113 @@ +/** + * 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.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import org.apache.hadoop.hbase.HBaseClassTestRule; +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.RegionLocations; +import org.apache.hadoop.hbase.ServerName; +import org.apache.hadoop.hbase.StartMiniClusterOption; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.RegionInfo; +import org.apache.hadoop.hbase.client.RegionLocateType; +import org.apache.hadoop.hbase.master.MetaLocationCache.CacheHolder; +import org.apache.hadoop.hbase.master.assignment.AssignmentManager; +import org.apache.hadoop.hbase.testclassification.MasterTests; +import org.apache.hadoop.hbase.testclassification.MediumTests; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +@Category({ MasterTests.class, MediumTests.class }) +public class TestBackupMasterSyncRoot { + + @ClassRule + public static final HBaseClassTestRule CLASS_RULE = + HBaseClassTestRule.forClass(TestBackupMasterSyncRoot.class); + + private static final HBaseTestingUtility UTIL = new HBaseTestingUtility(); + + @BeforeClass + public static void setUp() throws Exception { + UTIL.getConfiguration().setInt(MetaLocationCache.SYNC_INTERVAL_SECONDS, 1); + StartMiniClusterOption option = + StartMiniClusterOption.builder().numMasters(2).numRegionServers(3).build(); + UTIL.startMiniCluster(option); + UTIL.getAdmin().balancerSwitch(false, true); + } + + @AfterClass + public static void tearDown() throws IOException { + UTIL.shutdownMiniCluster(); + } + + @Test + public void testSync() throws Exception { + HMaster active = UTIL.getHBaseCluster().getMaster(); + AssignmentManager activeAM = active.getAssignmentManager(); + RegionInfo meta = + activeAM.getRegionStates().getRegionsOfTable(TableName.META_TABLE_NAME).get(0); + ServerName expected = activeAM.getRegionStates().getRegionStateNode(meta).getRegionLocation(); + HMaster backup = UTIL.getHBaseCluster().getMasterThreads().stream().map(t -> t.getMaster()) + .filter(h -> h != active).findFirst().get(); + MetaLocationCache cache = backup.getMetaLocationCache(); + UTIL.waitFor(10000, () -> { + RegionLocations loc = cache.locateMeta(HConstants.EMPTY_START_ROW, RegionLocateType.CURRENT); + return loc != null && loc.getRegionLocation().getServerName().equals(expected); + }); + CacheHolder currentHolder = cache.holder.get(); + assertNotNull(currentHolder); + long lastSyncSeqId = currentHolder.lastSyncSeqId; + long currentMVCC = active.masterRegion.getReadPoint(); + assertTrue(lastSyncSeqId <= currentMVCC); + TableName table = TableName.valueOf("test"); + UTIL.createTable(table, Bytes.toBytes("f")); + UTIL.waitTableAvailable(table); + long newMVCC = active.masterRegion.getReadPoint(); + // we have created several new procedures so the read point should be advanced + assertTrue(newMVCC > currentMVCC); + Thread.sleep(3000); + // should not change since the root family is not changed + assertSame(currentHolder, cache.holder.get()); + + ServerName newExpected = + UTIL.getAdmin().getRegionServers().stream().filter(s -> !s.equals(expected)).findAny().get(); + active.getAssignmentManager().moveAsync(new RegionPlan(meta, expected, newExpected)).get(); + assertEquals(newExpected, + activeAM.getRegionStates().getRegionStateNode(meta).getRegionLocation()); + UTIL.waitFor(10000, () -> { + RegionLocations loc = cache.locateMeta(HConstants.EMPTY_START_ROW, RegionLocateType.CURRENT); + return loc != null && loc.getRegionLocation().getServerName().equals(newExpected); + }); + CacheHolder newHolder = cache.holder.get(); + // this time the cache should be changed + assertNotSame(currentHolder, newHolder); + assertTrue(newHolder.lastSyncSeqId > newMVCC); + } +} diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCloseAnOpeningRegion.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCloseAnOpeningRegion.java index ecc5796..957eba5 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCloseAnOpeningRegion.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCloseAnOpeningRegion.java @@ -31,7 +31,7 @@ import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.master.assignment.AssignmentManager; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.regionserver.HRegionServer; import org.apache.hadoop.hbase.testclassification.MasterTests; import org.apache.hadoop.hbase.testclassification.MediumTests; @@ -71,8 +71,8 @@ public class TestCloseAnOpeningRegion { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManager(master, masterRegion) { + RootStore rootStore) { + return new AssignmentManager(master, rootStore) { @Override public ReportRegionStateTransitionResponse reportRegionStateTransition( diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestClusterRestartFailover.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestClusterRestartFailover.java index 7ec4c46..5f092e4 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestClusterRestartFailover.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestClusterRestartFailover.java @@ -39,7 +39,7 @@ import org.apache.hadoop.hbase.master.assignment.AssignmentManager; import org.apache.hadoop.hbase.master.assignment.ServerState; import org.apache.hadoop.hbase.master.assignment.ServerStateNode; import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.procedure2.Procedure; import org.apache.hadoop.hbase.test.MetricsAssertHelper; import org.apache.hadoop.hbase.testclassification.LargeTests; @@ -167,15 +167,15 @@ public class TestClusterRestartFailover extends AbstractTestRestartCluster { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManagerForTest(master, masterRegion); + RootStore rootStore) { + return new AssignmentManagerForTest(master, rootStore); } } private static final class AssignmentManagerForTest extends AssignmentManager { - public AssignmentManagerForTest(MasterServices master, MasterRegion masterRegion) { - super(master, masterRegion); + public AssignmentManagerForTest(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMetaLocationCache.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMetaLocationCache.java index 306767e..2e4d3af 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMetaLocationCache.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMetaLocationCache.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -45,6 +46,7 @@ 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.FutureUtils; +import org.apache.hadoop.hbase.util.Pair; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -99,7 +101,7 @@ public class TestMetaLocationCache { @Test public void testError() throws InterruptedException { AsyncClusterConnection conn = mock(AsyncClusterConnection.class); - when(conn.getAllMetaRegionLocations(anyInt())) + when(conn.syncRoot(anyLong(), anyInt())) .thenReturn(FutureUtils.failedFuture(new RuntimeException("inject error"))); when(master.getAsyncClusterConnection()).thenReturn(conn); Thread.sleep(2000); @@ -109,8 +111,8 @@ public class TestMetaLocationCache { HRegionLocation loc = new HRegionLocation(RegionInfoBuilder.newBuilder(TableName.META_TABLE_NAME).build(), ServerName.valueOf("localhost", 12345, System.currentTimeMillis())); - when(conn.getAllMetaRegionLocations(anyInt())) - .thenReturn(CompletableFuture.completedFuture(Arrays.asList(loc))); + when(conn.syncRoot(anyLong(), anyInt())) + .thenReturn(CompletableFuture.completedFuture(Pair.newPair(1L, Arrays.asList(loc)))); Thread.sleep(2000); List<HRegionLocation> list = cache.getAllMetaRegionLocations(false); assertEquals(1, list.size()); @@ -131,8 +133,8 @@ public class TestMetaLocationCache { ServerName.valueOf("127.0.0.2", 12345, System.currentTimeMillis())); HRegionLocation daughter2Loc = new HRegionLocation(daughter2, ServerName.valueOf("127.0.0.3", 12345, System.currentTimeMillis())); - when(conn.getAllMetaRegionLocations(anyInt())).thenReturn( - CompletableFuture.completedFuture(Arrays.asList(parentLoc, daughter1Loc, daughter2Loc))); + when(conn.syncRoot(anyLong(), anyInt())).thenReturn(CompletableFuture + .completedFuture(Pair.newPair(1L, Arrays.asList(parentLoc, daughter1Loc, daughter2Loc)))); when(master.getAsyncClusterConnection()).thenReturn(conn); Thread.sleep(2000); } 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 4bcecf1..345a6d2 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 @@ -52,6 +52,7 @@ import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher; import org.apache.hadoop.hbase.master.region.MasterRegion; import org.apache.hadoop.hbase.master.region.MasterRegionFactory; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.procedure2.ProcedureEvent; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility; @@ -110,9 +111,10 @@ public class MockMasterServices extends MockNoopMasterServices { conf.getBoolean(HBASE_SPLIT_WAL_COORDINATED_BY_ZK, DEFAULT_HBASE_SPLIT_COORDINATED_BY_ZK)? null: new SplitWALManager(this); this.masterRegion = MasterRegionFactory.create(this); + RootStore rootStore = new RootStore(masterRegion); // Mock an AM. this.assignmentManager = - new AssignmentManager(this, masterRegion, new MockRegionStateStore(this, masterRegion)) { + new AssignmentManager(this, rootStore, new MockRegionStateStore(this, rootStore)) { @Override public boolean isTableEnabled(final TableName tableName) { @@ -302,8 +304,8 @@ public class MockMasterServices extends MockNoopMasterServices { } private static class MockRegionStateStore extends RegionStateStore { - public MockRegionStateStore(MasterServices master, MasterRegion masterRegion) { - super(master, masterRegion); + public MockRegionStateStore(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestOpenRegionProcedureBackoff.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestOpenRegionProcedureBackoff.java index 227872a..8f0a5a1 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestOpenRegionProcedureBackoff.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestOpenRegionProcedureBackoff.java @@ -32,7 +32,7 @@ import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; import org.apache.hadoop.hbase.client.TableDescriptorBuilder; import org.apache.hadoop.hbase.master.HMaster; import org.apache.hadoop.hbase.master.MasterServices; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.testclassification.MasterTests; import org.apache.hadoop.hbase.testclassification.MediumTests; import org.apache.hadoop.hbase.util.Bytes; @@ -56,8 +56,8 @@ public class TestOpenRegionProcedureBackoff { private static final class AssignmentManagerForTest extends AssignmentManager { - public AssignmentManagerForTest(MasterServices master, MasterRegion masterRegion) { - super(master, masterRegion); + public AssignmentManagerForTest(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override @@ -77,8 +77,8 @@ public class TestOpenRegionProcedureBackoff { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManagerForTest(master, masterRegion); + RootStore rootStore) { + return new AssignmentManagerForTest(master, rootStore); } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestOpenRegionProcedureHang.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestOpenRegionProcedureHang.java index 57ce3a3..530f06e 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestOpenRegionProcedureHang.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestOpenRegionProcedureHang.java @@ -32,7 +32,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.procedure.MasterProcedureEnv; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.regionserver.HRegionServer; import org.apache.hadoop.hbase.testclassification.MasterTests; @@ -75,8 +75,8 @@ public class TestOpenRegionProcedureHang { private static final class AssignmentManagerForTest extends AssignmentManager { - public AssignmentManagerForTest(MasterServices master,MasterRegion masterRegion) { - super(master, masterRegion); + public AssignmentManagerForTest(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override @@ -112,8 +112,8 @@ public class TestOpenRegionProcedureHang { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManagerForTest(master, masterRegion); + RootStore rootStore) { + return new AssignmentManagerForTest(master, rootStore); } @Override diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRaceBetweenSCPAndDTP.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRaceBetweenSCPAndDTP.java index 6576eb7..107cf82 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRaceBetweenSCPAndDTP.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRaceBetweenSCPAndDTP.java @@ -31,7 +31,7 @@ import org.apache.hadoop.hbase.master.HMaster; import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.master.procedure.DisableTableProcedure; import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.procedure2.Procedure; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.testclassification.MasterTests; @@ -70,8 +70,8 @@ public class TestRaceBetweenSCPAndDTP { private static final class AssignmentManagerForTest extends AssignmentManager { - public AssignmentManagerForTest(MasterServices master, MasterRegion masterRegion) { - super(master,masterRegion); + public AssignmentManagerForTest(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override @@ -97,8 +97,8 @@ public class TestRaceBetweenSCPAndDTP { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManagerForTest(master, masterRegion); + RootStore rootStore) { + return new AssignmentManagerForTest(master, rootStore); } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRaceBetweenSCPAndTRSP.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRaceBetweenSCPAndTRSP.java index 65cef99..42d0c34 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRaceBetweenSCPAndTRSP.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestRaceBetweenSCPAndTRSP.java @@ -32,7 +32,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.procedure.ServerCrashProcedure; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.testclassification.LargeTests; import org.apache.hadoop.hbase.testclassification.MasterTests; @@ -70,8 +70,8 @@ public class TestRaceBetweenSCPAndTRSP { private static final class AssignmentManagerForTest extends AssignmentManager { - public AssignmentManagerForTest(MasterServices master, MasterRegion masterRegion) { - super(master, masterRegion); + public AssignmentManagerForTest(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override @@ -110,8 +110,8 @@ public class TestRaceBetweenSCPAndTRSP { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManagerForTest(master, masterRegion); + RootStore rootStore) { + return new AssignmentManagerForTest(master, rootStore); } } 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 dac471e..56caeec 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 @@ -37,7 +37,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.ServerManager; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.regionserver.HRegionServer; import org.apache.hadoop.hbase.testclassification.MasterTests; import org.apache.hadoop.hbase.testclassification.MediumTests; @@ -81,8 +81,8 @@ public class TestRegionAssignedToMultipleRegionServers { private static final class AssignmentManagerForTest extends AssignmentManager { - public AssignmentManagerForTest(MasterServices master, MasterRegion masterRegion) { - super(master, masterRegion); + public AssignmentManagerForTest(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override @@ -116,8 +116,8 @@ public class TestRegionAssignedToMultipleRegionServers { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManagerForTest(master, masterRegion); + RootStore rootStore) { + return new AssignmentManagerForTest(master, rootStore); } @Override diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportOnlineRegionsRace.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportOnlineRegionsRace.java index 2d0128a..217bde6 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportOnlineRegionsRace.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportOnlineRegionsRace.java @@ -39,7 +39,7 @@ import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.master.RegionState; import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.testclassification.MasterTests; import org.apache.hadoop.hbase.testclassification.MediumTests; @@ -69,8 +69,8 @@ public class TestReportOnlineRegionsRace { private static final class AssignmentManagerForTest extends AssignmentManager { - public AssignmentManagerForTest(MasterServices master, MasterRegion masterRegion) { - super(master, masterRegion); + public AssignmentManagerForTest(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override @@ -112,8 +112,8 @@ public class TestReportOnlineRegionsRace { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManagerForTest(master, masterRegion); + RootStore rootStore) { + return new AssignmentManagerForTest(master, rootStore); } } 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 41e884d..db9f45f 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 @@ -40,7 +40,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.ServerManager; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.regionserver.HRegionServer; import org.apache.hadoop.hbase.testclassification.MasterTests; import org.apache.hadoop.hbase.testclassification.MediumTests; @@ -83,8 +83,8 @@ public class TestReportRegionStateTransitionFromDeadServer { private static final class AssignmentManagerForTest extends AssignmentManager { - public AssignmentManagerForTest(MasterServices master, MasterRegion masterRegion) { - super(master, masterRegion); + public AssignmentManagerForTest(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override @@ -123,8 +123,8 @@ public class TestReportRegionStateTransitionFromDeadServer { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManagerForTest(master, masterRegion); + RootStore rootStore) { + return new AssignmentManagerForTest(master, rootStore); } @Override diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportRegionStateTransitionRetry.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportRegionStateTransitionRetry.java index 0943298..632801e 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportRegionStateTransitionRetry.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/assignment/TestReportRegionStateTransitionRetry.java @@ -36,7 +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.procedure.MasterProcedureEnv; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; import org.apache.hadoop.hbase.testclassification.MasterTests; import org.apache.hadoop.hbase.testclassification.MediumTests; @@ -61,8 +61,8 @@ public class TestReportRegionStateTransitionRetry { private static final class AssignmentManagerForTest extends AssignmentManager { - public AssignmentManagerForTest(MasterServices master, MasterRegion masterRegion) { - super(master, masterRegion); + public AssignmentManagerForTest(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override @@ -90,8 +90,8 @@ public class TestReportRegionStateTransitionRetry { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManagerForTest(master, masterRegion); + RootStore rootStore) { + return new AssignmentManagerForTest(master, rootStore); } } 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 ffca796..d4f1cf4 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 @@ -38,7 +38,7 @@ import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.master.ServerManager; import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.regionserver.HRegionServer; import org.apache.hadoop.hbase.testclassification.MasterTests; import org.apache.hadoop.hbase.testclassification.MediumTests; @@ -90,8 +90,8 @@ public class TestSCPGetRegionsRace { private static final class AssignmentManagerForTest extends AssignmentManager { - public AssignmentManagerForTest(MasterServices master, MasterRegion masterRegion) { - super(master, masterRegion); + public AssignmentManagerForTest(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override @@ -136,8 +136,8 @@ public class TestSCPGetRegionsRace { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AssignmentManagerForTest(master, masterRegion); + RootStore rootStore) { + return new AssignmentManagerForTest(master, rootStore); } @Override 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 fb0e460..943d51e 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 @@ -38,7 +38,7 @@ import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.master.RegionState; import org.apache.hadoop.hbase.master.ServerManager; -import org.apache.hadoop.hbase.master.region.MasterRegion; +import org.apache.hadoop.hbase.master.region.RootStore; import org.apache.hadoop.hbase.regionserver.HRegionServer; import org.apache.hadoop.hbase.regionserver.RSRpcServices; import org.apache.hadoop.hbase.testclassification.LargeTests; @@ -136,8 +136,8 @@ public class TestWakeUpUnexpectedProcedure { private static final class AMForTest extends AssignmentManager { - public AMForTest(MasterServices master, MasterRegion masterRegion) { - super(master, masterRegion); + public AMForTest(MasterServices master, RootStore rootStore) { + super(master, rootStore); } @Override @@ -204,8 +204,8 @@ public class TestWakeUpUnexpectedProcedure { @Override protected AssignmentManager createAssignmentManager(MasterServices master, - MasterRegion masterRegion) { - return new AMForTest(master, masterRegion); + RootStore rootStore) { + return new AMForTest(master, rootStore); } @Override diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java index 6007fd7..4092929 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java @@ -67,6 +67,11 @@ public class TestRegionMover2 { private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); + // when moving region, we first need to get the location of meta so it will call master inside the + // master rpc handler thread, which may cause dead lock if we have more than 3 threads here since + // we only have 3 rpc handlers for master in UT. + private static final int MAX_THREADS = 2; + @BeforeClass public static void setUpBeforeClass() throws Exception { TEST_UTIL.startMiniCluster(3); @@ -116,7 +121,7 @@ public class TestRegionMover2 { .collect(Collectors.toList()); RegionMover.RegionMoverBuilder rmBuilder = new RegionMover.RegionMoverBuilder(rsName, TEST_UTIL.getConfiguration()).ack(true) - .maxthreads(8); + .maxthreads(MAX_THREADS); try (RegionMover rm = rmBuilder.build()) { LOG.debug("Unloading {}", regionServer.getServerName()); rm.unload(); @@ -153,7 +158,7 @@ public class TestRegionMover2 { RegionMover.RegionMoverBuilder rmBuilder = new RegionMover.RegionMoverBuilder(rsName, TEST_UTIL.getConfiguration()).ack(true) - .maxthreads(8); + .maxthreads(MAX_THREADS); try (RegionMover rm = rmBuilder.build()) { LOG.debug("Unloading {}", regionServer.getServerName()); rm.unload(); @@ -194,13 +199,13 @@ public class TestRegionMover2 { admin.flush(tableName); HRegionServer regionServer = cluster.getRegionServer(0); String rsName = regionServer.getServerName().getAddress().toString(); - int numRegions = regionServer.getNumberOfOnlineRegions(); + regionServer.getNumberOfOnlineRegions(); List<HRegion> hRegions = regionServer.getRegions().stream() .filter(hRegion -> hRegion.getRegionInfo().getTable().equals(tableName)) .collect(Collectors.toList()); RegionMover.RegionMoverBuilder rmBuilder = new RegionMover.RegionMoverBuilder(rsName, TEST_UTIL.getConfiguration()).ack(true) - .maxthreads(8); + .maxthreads(MAX_THREADS); try (RegionMover rm = rmBuilder.build()) { LOG.debug("Unloading {}", regionServer.getServerName()); rm.unload();