From e3fc2795756c36fe835a25003537cb355a23e8a4 Mon Sep 17 00:00:00 2001 From: Wellington Chevreuil Date: Thu, 21 Nov 2019 22:52:58 +0000 Subject: [PATCH 1/5] HBASE-23313 [hbck2] setRegionState should update Master in-memory state too --- .../apache/hadoop/hbase/client/HBaseHbck.java | 20 +++- .../org/apache/hadoop/hbase/client/Hbck.java | 9 ++ .../hbase/client/RegionInfoBuilder.java | 5 + .../hbase/shaded/protobuf/ProtobufUtil.java | 11 ++ .../shaded/protobuf/RequestConverter.java | 12 ++ .../hbase/client/example/HbckClient.java | 109 ++++++++++++++++++ .../src/main/protobuf/HBase.proto | 1 + .../src/main/protobuf/Master.proto | 13 +++ .../hbase/master/MasterRpcServices.java | 35 ++++++ 9 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java index f2bfac02b4c1..6c15155387cc 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java @@ -26,6 +26,8 @@ import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.ipc.RpcControllerFactory; +import org.apache.hadoop.hbase.master.RegionState; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos; import org.apache.yetus.audience.InterfaceAudience; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -98,8 +100,8 @@ public boolean isAborted() { public TableState setTableStateInMeta(TableState state) throws IOException { try { GetTableStateResponse response = hbck.setTableStateInMeta( - rpcControllerFactory.newController(), - RequestConverter.buildSetTableStateInMetaRequest(state)); + rpcControllerFactory.newController(), + RequestConverter.buildSetTableStateInMetaRequest(state)); return TableState.convert(state.getTableName(), response.getTableState()); } catch (ServiceException se) { LOG.debug("table={}, state={}", state.getTableName(), state.getState(), se); @@ -107,6 +109,20 @@ public TableState setTableStateInMeta(TableState state) throws IOException { } } + @Override + public RegionState setRegionStateInMeta(RegionState state) throws IOException { + try { + LOG.trace("RegionInfo from state: {}", state.getRegion().getEncodedName()); + MasterProtos.GetRegionStateResponse response = hbck.setRegionStateInMeta( + rpcControllerFactory.newController(), + RequestConverter.buildSetRegionStateInMetaRequest(state)); + return RegionState.convert(response.getRegionState()); + } catch (ServiceException se) { + LOG.debug("region={}, state={}", state.getRegion().getRegionName(), state.getState(), se); + throw new IOException(se); + } + } + @Override public List assigns(List encodedRegionNames, boolean override) throws IOException { diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java index 4f37f130593b..fbcb8d8edbc5 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java @@ -27,6 +27,7 @@ import org.apache.hadoop.hbase.HBaseInterfaceAudience; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.master.RegionState; import org.apache.yetus.audience.InterfaceAudience; import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; @@ -54,6 +55,14 @@ public interface Hbck extends Abortable, Closeable { */ TableState setTableStateInMeta(TableState state) throws IOException; + /** + * Update region state in Meta only. No procedures are submitted to manipulate the given region + * or any other region from same table. + * @param state region state + * @return previous state of the region in Meta + */ + RegionState setRegionStateInMeta(RegionState state) throws IOException; + /** * Like {@link Admin#assign(byte[])} but 'raw' in that it can do more than one Region at a time * -- good if many Regions to online -- and it will schedule the assigns even in the case where diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoBuilder.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoBuilder.java index cd9e40b95243..e79a7b76cdbf 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoBuilder.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoBuilder.java @@ -116,6 +116,11 @@ public RegionInfoBuilder setOffline(boolean offLine) { return this; } + public RegionInfoBuilder setEncodedName(String encodedName) { + this.encodedName = encodedName; + return this; + } + public RegionInfo build() { return new MutableRegionInfo(tableName, startKey, endKey, split, regionId, replicaId, offLine, regionName, encodedName); diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java index 94a2805b61cc..5085b5f549ff 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java @@ -2226,6 +2226,14 @@ public static HBaseProtos.TableName toProtoTableName(TableName tableName) { .setQualifier(UnsafeByteOperations.unsafeWrap(tableName.getQualifier())).build(); } + public static HBaseProtos.RegionInfo toProtoRegionInfo( + org.apache.hadoop.hbase.client.RegionInfo regionInfo) { + return HBaseProtos.RegionInfo.newBuilder() + .setRegionId(regionInfo.getRegionId()) + .setRegionEncodedName(regionInfo.getEncodedName()) + .setTableName(toProtoTableName(regionInfo.getTable())).build(); + } + public static List toTableNameList(List tableNamesList) { if (tableNamesList == null) { return new ArrayList<>(); @@ -3184,6 +3192,9 @@ public static org.apache.hadoop.hbase.client.RegionInfo toRegionInfo(final HBase if (proto.hasOffline()) { rib.setOffline(proto.getOffline()); } + if (proto.hasRegionEncodedName()) { + rib.setEncodedName(proto.getRegionEncodedName()); + } return rib.build(); } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java index d45423c95b01..d45f855dcfbb 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java @@ -56,6 +56,7 @@ import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.filter.ByteArrayComparable; import org.apache.hadoop.hbase.io.TimeRange; +import org.apache.hadoop.hbase.master.RegionState; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.SyncReplicationState; import org.apache.hadoop.hbase.util.Bytes; @@ -112,6 +113,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableTableRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetClusterStatusRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetNamespaceDescriptorRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetRegionStateInMetaRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableNamesRequest; @@ -1444,6 +1446,16 @@ public static SetTableStateInMetaRequest buildSetTableStateInMetaRequest(final T .setTableName(ProtobufUtil.toProtoTableName(state.getTableName())).build(); } + /** + * Creates a protocol buffer SetRegionStateInMetaRequest + * @param state region state to update in Meta + * @return a SetRegionStateInMetaRequest + */ + public static SetRegionStateInMetaRequest buildSetRegionStateInMetaRequest(final RegionState state) { + return SetRegionStateInMetaRequest.newBuilder().setRegionState(state.convert()) + .setRegionInfo(ProtobufUtil.toProtoRegionInfo(state.getRegion())).build(); + } + /** * Creates a protocol buffer GetTableDescriptorsRequest for a single table * diff --git a/hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java b/hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java new file mode 100644 index 000000000000..877b97a62af8 --- /dev/null +++ b/hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java @@ -0,0 +1,109 @@ +package org.apache.hadoop.hbase.client.example; +/** + * 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. + */ + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.AsyncConnection; +import org.apache.hadoop.hbase.client.ConnectionFactory; +import org.apache.hadoop.hbase.client.RegionInfo; +import org.apache.hadoop.hbase.master.RegionState; +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.yetus.audience.InterfaceAudience; + +@InterfaceAudience.Private +public class HbckClient { + + public static void main(String[] args) throws Exception { + Configuration conf = HBaseConfiguration.create(); + try(AsyncConnection conn = ConnectionFactory.createAsyncConnection(conf).get()){ + RegionInfo info = new RegionInfo() { + @Override public String getShortNameToLog() { + return null; + } + + @Override public long getRegionId() { + return 0; + } + + @Override public byte[] getRegionName() { + return new byte[0]; + } + + @Override public String getRegionNameAsString() { + return null; + } + + @Override public String getEncodedName() { + return args[0]; + } + + @Override public byte[] getEncodedNameAsBytes() { + return Bytes.toBytes(args[0]); + } + + @Override public byte[] getStartKey() { + return new byte[0]; + } + + @Override public byte[] getEndKey() { + return new byte[0]; + } + + @Override public TableName getTable() { + return TableName.valueOf("fake-name"); + } + + @Override public int getReplicaId() { + return 0; + } + + @Override public boolean isSplit() { + return false; + } + + @Override public boolean isOffline() { + return false; + } + + @Override public boolean isSplitParent() { + return false; + } + + @Override public boolean isMetaRegion() { + return false; + } + + @Override public boolean containsRange(byte[] rangeStartKey, byte[] rangeEndKey) { + return false; + } + + @Override public boolean containsRow(byte[] row) { + return false; + } + }; + RegionState state = RegionState.createForTesting(info, RegionState.State.valueOf(args[1])); + System.out.println(">>>> " + state.getRegion().getEncodedName()); + RegionState result = conn.getHbck().get().setRegionStateInMeta(state); + System.out.println("Successfully changed region from state " + result.getState().name() + + " to state " + args[1]); + } + + } +} diff --git a/hbase-protocol-shaded/src/main/protobuf/HBase.proto b/hbase-protocol-shaded/src/main/protobuf/HBase.proto index d06bc8b42d3e..cf577e93ef76 100644 --- a/hbase-protocol-shaded/src/main/protobuf/HBase.proto +++ b/hbase-protocol-shaded/src/main/protobuf/HBase.proto @@ -79,6 +79,7 @@ message RegionInfo { optional bool offline = 5; optional bool split = 6; optional int32 replica_id = 7 [default = 0]; + optional string region_encoded_name = 8; } /** diff --git a/hbase-protocol-shaded/src/main/protobuf/Master.proto b/hbase-protocol-shaded/src/main/protobuf/Master.proto index fee9ab8419d1..5a7902f4087b 100644 --- a/hbase-protocol-shaded/src/main/protobuf/Master.proto +++ b/hbase-protocol-shaded/src/main/protobuf/Master.proto @@ -517,6 +517,10 @@ message GetTableStateResponse { required TableState table_state = 1; } +message GetRegionStateResponse { + required RegionState region_state = 1; +} + message GetClusterStatusRequest { repeated Option options = 1; @@ -1090,6 +1094,11 @@ message SetTableStateInMetaRequest { required TableState table_state = 2; } +message SetRegionStateInMetaRequest { + required RegionInfo region_info = 1; + required RegionState region_state = 2; +} + /** Like Admin's AssignRegionRequest except it can * take one or more Regions at a time. */ @@ -1152,6 +1161,10 @@ service HbckService { rpc SetTableStateInMeta(SetTableStateInMetaRequest) returns(GetTableStateResponse); + /** Update state of the table in meta only*/ + rpc SetRegionStateInMeta(SetRegionStateInMetaRequest) + returns(GetRegionStateResponse); + /** * Assign regions. * Like Admin's assign but works even if the 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 92f8178a197e..58ebc1a40762 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 @@ -48,6 +48,7 @@ import org.apache.hadoop.hbase.UnknownRegionException; import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; import org.apache.hadoop.hbase.client.MasterSwitchType; +import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionInfoBuilder; import org.apache.hadoop.hbase.client.Table; @@ -2465,6 +2466,39 @@ public GetTableStateResponse setTableStateInMeta(RpcController controller, } } + /** + * Update state of the region in meta only. This is required by hbck in some situations to cleanup + * stuck assign/ unassign regions procedures for the table. + * + * @return previous state of the region + */ + @Override + public MasterProtos.GetRegionStateResponse setRegionStateInMeta(RpcController controller, + MasterProtos.SetRegionStateInMetaRequest request) throws ServiceException { + try { + RegionInfo info = this.master.getAssignmentManager(). + loadRegionFromMeta(request.getRegionInfo().getRegionEncodedName()); + LOG.trace("region info loaded from meta table: {}", info); + RegionState prevState = this.master.getAssignmentManager().getRegionStates(). + getRegionState(info); + RegionState newState = RegionState.convert(request.getRegionState()); + LOG.info("{} set region={} state from {} to {}", master.getClientIdAuditPrefix(), + info, prevState.getState(), newState.getState()); + Put metaPut = MetaTableAccessor.makePutFromRegionInfo(info, System.currentTimeMillis()); + metaPut.addColumn(HConstants.CATALOG_FAMILY, + HConstants.STATE_QUALIFIER, Bytes.toBytes(newState.getState().name())); + List putList = new ArrayList<>(); + putList.add(metaPut); + MetaTableAccessor.putsToMetaTable(this.master.getConnection(), putList); + //Loads from meta again to refresh AM cache with the new region state + this.master.getAssignmentManager().loadRegionFromMeta(info.getEncodedName()); + return MasterProtos.GetRegionStateResponse.newBuilder(). + setRegionState(prevState.convert()).build(); + } catch (Exception e) { + throw new ServiceException(e); + } + } + /** * Get RegionInfo from Master using content of RegionSpecifier as key. * @return RegionInfo found by decoding rs or null if none found @@ -2834,4 +2868,5 @@ private boolean shouldSubmitSCP(ServerName serverName) { } return true; } + } From 303e61bda30cb8e9c4bb4ad81b365b480b9e0a62 Mon Sep 17 00:00:00 2001 From: Wellington Chevreuil Date: Fri, 22 Nov 2019 11:18:52 +0000 Subject: [PATCH 2/5] addressing checkstyles complaints from previous build; Added related UT to TestHbck --- .../apache/hadoop/hbase/client/HBaseHbck.java | 4 ++-- .../shaded/protobuf/RequestConverter.java | 5 +++-- .../hbase/client/example/HbckClient.java | 1 - .../apache/hadoop/hbase/client/TestHbck.java | 18 ++++++++++++++++++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java index 6c15155387cc..9cc1cb700e2c 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java @@ -26,16 +26,16 @@ import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.ipc.RpcControllerFactory; -import org.apache.hadoop.hbase.master.RegionState; -import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos; import org.apache.yetus.audience.InterfaceAudience; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; +import org.apache.hadoop.hbase.master.RegionState; import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AssignsResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.BypassProcedureRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.BypassProcedureResponse; diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java index d45f855dcfbb..fda02eccec05 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java @@ -113,7 +113,6 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableTableRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetClusterStatusRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetNamespaceDescriptorRequest; -import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetRegionStateInMetaRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableNamesRequest; @@ -139,6 +138,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetCleanerChoreRunningRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormalizerRunningRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetRegionStateInMetaRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos .SetSnapshotCleanupRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSplitOrMergeEnabledRequest; @@ -1451,7 +1451,8 @@ public static SetTableStateInMetaRequest buildSetTableStateInMetaRequest(final T * @param state region state to update in Meta * @return a SetRegionStateInMetaRequest */ - public static SetRegionStateInMetaRequest buildSetRegionStateInMetaRequest(final RegionState state) { + public static SetRegionStateInMetaRequest buildSetRegionStateInMetaRequest( + final RegionState state) { return SetRegionStateInMetaRequest.newBuilder().setRegionState(state.convert()) .setRegionInfo(ProtobufUtil.toProtoRegionInfo(state.getRegion())).build(); } diff --git a/hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java b/hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java index 877b97a62af8..3d23405f9649 100644 --- a/hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java +++ b/hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java @@ -99,7 +99,6 @@ public static void main(String[] args) throws Exception { } }; RegionState state = RegionState.createForTesting(info, RegionState.State.valueOf(args[1])); - System.out.println(">>>> " + state.getRegion().getEncodedName()); RegionState result = conn.getHbck().get().setRegionStateInMeta(state); System.out.println("Successfully changed region from state " + result.getState().name() + " to state " + args[1]); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java index 070cfe0c38b3..c8b3d45163df 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java @@ -38,6 +38,7 @@ import org.apache.hadoop.hbase.coprocessor.ObserverContext; import org.apache.hadoop.hbase.master.HMaster; import org.apache.hadoop.hbase.master.RegionState; +import org.apache.hadoop.hbase.master.assignment.AssignmentManager; import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; import org.apache.hadoop.hbase.master.procedure.TableProcedureInterface; import org.apache.hadoop.hbase.procedure2.Procedure; @@ -182,6 +183,23 @@ public void testSetTableStateInMeta() throws Exception { prevState.isDisabled()); } + @Test + public void testSetRegionStateInMEta() throws Exception { + Hbck hbck = getHbck(); + try(Admin admin = TEST_UTIL.getAdmin()){ + RegionInfo region = admin.getRegions(TABLE_NAME).get(0); + AssignmentManager am = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager(); + RegionState prevState = am.getRegionStates().getRegionState(region); + RegionState newState = RegionState.createForTesting(region, + RegionState.State.CLOSED); + RegionState result = hbck.setRegionStateInMeta(newState); + assertEquals(prevState.getState(), result.getState()); + RegionState cachedState = am.getRegionStates().getRegionState(region.getEncodedName()); + assertEquals(newState.getState(), cachedState.getState()); + hbck.setRegionStateInMeta(prevState); + } + } + @Test public void testAssigns() throws Exception { Hbck hbck = getHbck(); From 8127ba271fc0b8ab6f4245289467b508d2dcaecd Mon Sep 17 00:00:00 2001 From: Wellington Chevreuil Date: Fri, 22 Nov 2019 16:27:28 +0000 Subject: [PATCH 3/5] another attempt to address checkstyle complaints about order of imports. Removed HbckClient.java as now have proper UT for this new method. --- .../apache/hadoop/hbase/client/HBaseHbck.java | 19 +-- .../hbase/client/example/HbckClient.java | 108 ------------------ 2 files changed, 10 insertions(+), 117 deletions(-) delete mode 100644 hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java index 9cc1cb700e2c..d2ffe243a60c 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java @@ -19,20 +19,14 @@ import java.io.IOException; import java.util.List; -import java.util.Map; import java.util.concurrent.Callable; import java.util.stream.Collectors; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.ServerName; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.ipc.RpcControllerFactory; -import org.apache.yetus.audience.InterfaceAudience; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.ipc.RpcControllerFactory; import org.apache.hadoop.hbase.master.RegionState; +import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos; @@ -47,6 +41,13 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ScheduleServerCrashProcedureResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.UnassignsResponse; +import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; + +import org.apache.yetus.audience.InterfaceAudience; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Use {@link Connection#getHbck()} to obtain an instance of {@link Hbck} instead of * constructing an HBaseHbck directly. diff --git a/hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java b/hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java deleted file mode 100644 index 3d23405f9649..000000000000 --- a/hbase-examples/src/main/java/org/apache/hadoop/hbase/client/example/HbckClient.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.apache.hadoop.hbase.client.example; -/** - * 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. - */ - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.HBaseConfiguration; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.client.AsyncConnection; -import org.apache.hadoop.hbase.client.ConnectionFactory; -import org.apache.hadoop.hbase.client.RegionInfo; -import org.apache.hadoop.hbase.master.RegionState; -import org.apache.hadoop.hbase.util.Bytes; -import org.apache.yetus.audience.InterfaceAudience; - -@InterfaceAudience.Private -public class HbckClient { - - public static void main(String[] args) throws Exception { - Configuration conf = HBaseConfiguration.create(); - try(AsyncConnection conn = ConnectionFactory.createAsyncConnection(conf).get()){ - RegionInfo info = new RegionInfo() { - @Override public String getShortNameToLog() { - return null; - } - - @Override public long getRegionId() { - return 0; - } - - @Override public byte[] getRegionName() { - return new byte[0]; - } - - @Override public String getRegionNameAsString() { - return null; - } - - @Override public String getEncodedName() { - return args[0]; - } - - @Override public byte[] getEncodedNameAsBytes() { - return Bytes.toBytes(args[0]); - } - - @Override public byte[] getStartKey() { - return new byte[0]; - } - - @Override public byte[] getEndKey() { - return new byte[0]; - } - - @Override public TableName getTable() { - return TableName.valueOf("fake-name"); - } - - @Override public int getReplicaId() { - return 0; - } - - @Override public boolean isSplit() { - return false; - } - - @Override public boolean isOffline() { - return false; - } - - @Override public boolean isSplitParent() { - return false; - } - - @Override public boolean isMetaRegion() { - return false; - } - - @Override public boolean containsRange(byte[] rangeStartKey, byte[] rangeEndKey) { - return false; - } - - @Override public boolean containsRow(byte[] row) { - return false; - } - }; - RegionState state = RegionState.createForTesting(info, RegionState.State.valueOf(args[1])); - RegionState result = conn.getHbck().get().setRegionStateInMeta(state); - System.out.println("Successfully changed region from state " + result.getState().name() + - " to state " + args[1]); - } - - } -} From e540f149fa9bc8701281bcf9a5be905c2b9ea702 Mon Sep 17 00:00:00 2001 From: Wellington Chevreuil Date: Sat, 23 Nov 2019 14:36:30 +0000 Subject: [PATCH 4/5] changed to receive list of several RegionStates in a single RPC --- .../apache/hadoop/hbase/client/HBaseHbck.java | 18 ++++-- .../org/apache/hadoop/hbase/client/Hbck.java | 4 +- .../hbase/shaded/protobuf/ProtobufUtil.java | 1 + .../shaded/protobuf/RequestConverter.java | 9 +-- .../src/main/protobuf/Master.proto | 11 ++-- .../hbase/master/MasterRpcServices.java | 55 ++++++++++--------- .../apache/hadoop/hbase/client/TestHbck.java | 39 +++++++++---- 7 files changed, 83 insertions(+), 54 deletions(-) diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java index d2ffe243a60c..b92629be260b 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java @@ -18,6 +18,7 @@ package org.apache.hadoop.hbase.client; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.stream.Collectors; @@ -111,15 +112,20 @@ public TableState setTableStateInMeta(TableState state) throws IOException { } @Override - public RegionState setRegionStateInMeta(RegionState state) throws IOException { + public List setRegionStateInMeta(List states) throws IOException { try { - LOG.trace("RegionInfo from state: {}", state.getRegion().getEncodedName()); - MasterProtos.GetRegionStateResponse response = hbck.setRegionStateInMeta( + if(LOG.isDebugEnabled()) { + states.forEach(s -> + LOG.debug("region={}, state={}", s.getRegion().getRegionName(), s.getState()) + ); + } + MasterProtos.GetRegionStateInMetaResponse response = hbck.setRegionStateInMeta( rpcControllerFactory.newController(), - RequestConverter.buildSetRegionStateInMetaRequest(state)); - return RegionState.convert(response.getRegionState()); + RequestConverter.buildSetRegionStateInMetaRequest(states)); + final List result = new ArrayList<>(); + response.getStatesList().forEach( s -> result.add(RegionState.convert(s))); + return result; } catch (ServiceException se) { - LOG.debug("region={}, state={}", state.getRegion().getRegionName(), state.getState(), se); throw new IOException(se); } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java index fbcb8d8edbc5..ff982b2ef978 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java @@ -58,10 +58,10 @@ public interface Hbck extends Abortable, Closeable { /** * Update region state in Meta only. No procedures are submitted to manipulate the given region * or any other region from same table. - * @param state region state + * @param states list of all region states to be updated in meta * @return previous state of the region in Meta */ - RegionState setRegionStateInMeta(RegionState state) throws IOException; + List setRegionStateInMeta(List states) throws IOException; /** * Like {@link Admin#assign(byte[])} but 'raw' in that it can do more than one Region at a time diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java index 5085b5f549ff..c6e48d420148 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java @@ -3153,6 +3153,7 @@ public static HBaseProtos.RegionInfo toRegionInfo(final org.apache.hadoop.hbase. builder.setOffline(info.isOffline()); builder.setSplit(info.isSplit()); builder.setReplicaId(info.getReplicaId()); + builder.setRegionEncodedName(info.getEncodedName()); return builder.build(); } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java index fda02eccec05..eab4c4118759 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java @@ -1448,13 +1448,14 @@ public static SetTableStateInMetaRequest buildSetTableStateInMetaRequest(final T /** * Creates a protocol buffer SetRegionStateInMetaRequest - * @param state region state to update in Meta + * @param states list of regions states to update in Meta * @return a SetRegionStateInMetaRequest */ public static SetRegionStateInMetaRequest buildSetRegionStateInMetaRequest( - final RegionState state) { - return SetRegionStateInMetaRequest.newBuilder().setRegionState(state.convert()) - .setRegionInfo(ProtobufUtil.toProtoRegionInfo(state.getRegion())).build(); + final List states) { + final SetRegionStateInMetaRequest.Builder builder = SetRegionStateInMetaRequest.newBuilder(); + states.forEach(s -> builder.addStates(s.convert())); + return builder.build(); } /** diff --git a/hbase-protocol-shaded/src/main/protobuf/Master.proto b/hbase-protocol-shaded/src/main/protobuf/Master.proto index 5a7902f4087b..69377a62b11b 100644 --- a/hbase-protocol-shaded/src/main/protobuf/Master.proto +++ b/hbase-protocol-shaded/src/main/protobuf/Master.proto @@ -517,8 +517,8 @@ message GetTableStateResponse { required TableState table_state = 1; } -message GetRegionStateResponse { - required RegionState region_state = 1; +message GetRegionStateInMetaResponse { + repeated RegionState states = 1; } @@ -1095,8 +1095,7 @@ message SetTableStateInMetaRequest { } message SetRegionStateInMetaRequest { - required RegionInfo region_info = 1; - required RegionState region_state = 2; + repeated RegionState states = 2; } /** Like Admin's AssignRegionRequest except it can @@ -1161,9 +1160,9 @@ service HbckService { rpc SetTableStateInMeta(SetTableStateInMetaRequest) returns(GetTableStateResponse); - /** Update state of the table in meta only*/ + /** Update state of the region in meta only*/ rpc SetRegionStateInMeta(SetRegionStateInMetaRequest) - returns(GetRegionStateResponse); + returns(GetRegionStateInMetaResponse); /** * Assign regions. 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 58ebc1a40762..5ef32dae0108 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 @@ -198,6 +198,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProcedureResultResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProceduresRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProceduresResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetRegionStateInMetaResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetSchemaAlterStatusResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsRequest; @@ -277,6 +278,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormalizerRunningResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetRegionStateInMetaRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos .SetSnapshotCleanupRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos @@ -2470,33 +2472,36 @@ public GetTableStateResponse setTableStateInMeta(RpcController controller, * Update state of the region in meta only. This is required by hbck in some situations to cleanup * stuck assign/ unassign regions procedures for the table. * - * @return previous state of the region + * @return previous states of the regions */ @Override - public MasterProtos.GetRegionStateResponse setRegionStateInMeta(RpcController controller, - MasterProtos.SetRegionStateInMetaRequest request) throws ServiceException { - try { - RegionInfo info = this.master.getAssignmentManager(). - loadRegionFromMeta(request.getRegionInfo().getRegionEncodedName()); - LOG.trace("region info loaded from meta table: {}", info); - RegionState prevState = this.master.getAssignmentManager().getRegionStates(). - getRegionState(info); - RegionState newState = RegionState.convert(request.getRegionState()); - LOG.info("{} set region={} state from {} to {}", master.getClientIdAuditPrefix(), - info, prevState.getState(), newState.getState()); - Put metaPut = MetaTableAccessor.makePutFromRegionInfo(info, System.currentTimeMillis()); - metaPut.addColumn(HConstants.CATALOG_FAMILY, - HConstants.STATE_QUALIFIER, Bytes.toBytes(newState.getState().name())); - List putList = new ArrayList<>(); - putList.add(metaPut); - MetaTableAccessor.putsToMetaTable(this.master.getConnection(), putList); - //Loads from meta again to refresh AM cache with the new region state - this.master.getAssignmentManager().loadRegionFromMeta(info.getEncodedName()); - return MasterProtos.GetRegionStateResponse.newBuilder(). - setRegionState(prevState.convert()).build(); - } catch (Exception e) { - throw new ServiceException(e); - } + public GetRegionStateInMetaResponse setRegionStateInMeta(RpcController controller, + SetRegionStateInMetaRequest request) throws ServiceException { + final GetRegionStateInMetaResponse.Builder builder = GetRegionStateInMetaResponse.newBuilder(); + for(ClusterStatusProtos.RegionState s : request.getStatesList()) { + try { + RegionInfo info = this.master.getAssignmentManager(). + loadRegionFromMeta(s.getRegionInfo().getRegionEncodedName()); + LOG.trace("region info loaded from meta table: {}", info); + RegionState prevState = this.master.getAssignmentManager().getRegionStates(). + getRegionState(info); + RegionState newState = RegionState.convert(s); + LOG.info("{} set region={} state from {} to {}", master.getClientIdAuditPrefix(), info, + prevState.getState(), newState.getState()); + Put metaPut = MetaTableAccessor.makePutFromRegionInfo(info, System.currentTimeMillis()); + metaPut.addColumn(HConstants.CATALOG_FAMILY, HConstants.STATE_QUALIFIER, + Bytes.toBytes(newState.getState().name())); + List putList = new ArrayList<>(); + putList.add(metaPut); + MetaTableAccessor.putsToMetaTable(this.master.getConnection(), putList); + //Loads from meta again to refresh AM cache with the new region state + this.master.getAssignmentManager().loadRegionFromMeta(info.getEncodedName()); + builder.addStates(prevState.convert()); + } catch (Exception e) { + throw new ServiceException(e); + } + } + return builder.build(); } /** diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java index c8b3d45163df..8a0e8f45990d 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java @@ -21,8 +21,11 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.concurrent.CountDownLatch; import java.util.stream.Collectors; @@ -49,6 +52,7 @@ import org.apache.hadoop.hbase.testclassification.ClientTests; import org.apache.hadoop.hbase.testclassification.LargeTests; import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.util.Pair; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -184,19 +188,32 @@ public void testSetTableStateInMeta() throws Exception { } @Test - public void testSetRegionStateInMEta() throws Exception { + public void testSetRegionStateInMeta() throws Exception { Hbck hbck = getHbck(); try(Admin admin = TEST_UTIL.getAdmin()){ - RegionInfo region = admin.getRegions(TABLE_NAME).get(0); - AssignmentManager am = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager(); - RegionState prevState = am.getRegionStates().getRegionState(region); - RegionState newState = RegionState.createForTesting(region, - RegionState.State.CLOSED); - RegionState result = hbck.setRegionStateInMeta(newState); - assertEquals(prevState.getState(), result.getState()); - RegionState cachedState = am.getRegionStates().getRegionState(region.getEncodedName()); - assertEquals(newState.getState(), cachedState.getState()); - hbck.setRegionStateInMeta(prevState); + final List regions = admin.getRegions(TABLE_NAME); + final AssignmentManager am = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager(); + final List prevStates = new ArrayList<>(); + final List newStates = new ArrayList<>(); + final Map> regionsMap = new HashMap<>(); + regions.forEach( r -> { + RegionState prevState = am.getRegionStates().getRegionState(r); + prevStates.add(prevState); + RegionState newState = RegionState.createForTesting(r, RegionState.State.CLOSED); + newStates.add(newState); + regionsMap.put(r.getEncodedName(), new Pair<>(prevState, newState)); + }); + final List result = hbck.setRegionStateInMeta(newStates); + result.forEach( r -> { + RegionState prevState = regionsMap.get(r.getRegion().getEncodedName()).getFirst(); + assertEquals(prevState.getState(), r.getState()); + }); + regions.forEach(r -> { + RegionState cachedState = am.getRegionStates().getRegionState(r.getEncodedName()); + RegionState newState = regionsMap.get(r.getEncodedName()).getSecond(); + assertEquals(newState.getState(), cachedState.getState()); + }); + hbck.setRegionStateInMeta(prevStates); } } From 47b34bcd5a325321817d47a899a779210e9ce007 Mon Sep 17 00:00:00 2001 From: Wellington Chevreuil Date: Mon, 25 Nov 2019 11:55:28 +0000 Subject: [PATCH 5/5] addressing the whitespace checkstyle issues --- .../main/java/org/apache/hadoop/hbase/client/HBaseHbck.java | 2 +- .../test/java/org/apache/hadoop/hbase/client/TestHbck.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java index b92629be260b..651922ea7c96 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java @@ -123,7 +123,7 @@ public List setRegionStateInMeta(List states) throws I rpcControllerFactory.newController(), RequestConverter.buildSetRegionStateInMetaRequest(states)); final List result = new ArrayList<>(); - response.getStatesList().forEach( s -> result.add(RegionState.convert(s))); + response.getStatesList().forEach(s -> result.add(RegionState.convert(s))); return result; } catch (ServiceException se) { throw new IOException(se); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java index 8a0e8f45990d..a77c687b1377 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java @@ -196,7 +196,7 @@ public void testSetRegionStateInMeta() throws Exception { final List prevStates = new ArrayList<>(); final List newStates = new ArrayList<>(); final Map> regionsMap = new HashMap<>(); - regions.forEach( r -> { + regions.forEach(r -> { RegionState prevState = am.getRegionStates().getRegionState(r); prevStates.add(prevState); RegionState newState = RegionState.createForTesting(r, RegionState.State.CLOSED); @@ -204,7 +204,7 @@ public void testSetRegionStateInMeta() throws Exception { regionsMap.put(r.getEncodedName(), new Pair<>(prevState, newState)); }); final List result = hbck.setRegionStateInMeta(newStates); - result.forEach( r -> { + result.forEach(r -> { RegionState prevState = regionsMap.get(r.getRegion().getEncodedName()).getFirst(); assertEquals(prevState.getState(), r.getState()); });