Skip to content

Commit 636fa2c

Browse files
authored
HBASE-23313 [hbck2] setRegionState should update Master in-memory sta… (#864)
Signed-off-by: Mingliang Liu <[email protected]> Signed-off-by: stack <[email protected]>
1 parent 0d7a6b9 commit 636fa2c

File tree

9 files changed

+162
-11
lines changed

9 files changed

+162
-11
lines changed

hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,19 @@
1818
package org.apache.hadoop.hbase.client;
1919

2020
import java.io.IOException;
21+
import java.util.ArrayList;
2122
import java.util.List;
22-
import java.util.Map;
2323
import java.util.concurrent.Callable;
2424
import java.util.stream.Collectors;
25-
import org.apache.hadoop.conf.Configuration;
26-
import org.apache.hadoop.hbase.ServerName;
27-
import org.apache.hadoop.hbase.TableName;
28-
import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
29-
import org.apache.yetus.audience.InterfaceAudience;
30-
import org.slf4j.Logger;
31-
import org.slf4j.LoggerFactory;
3225

33-
import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException;
26+
import org.apache.hadoop.conf.Configuration;
3427

28+
import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
29+
import org.apache.hadoop.hbase.master.RegionState;
30+
import org.apache.hadoop.hbase.ServerName;
3531
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
3632
import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;
33+
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos;
3734
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AssignsResponse;
3835
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.BypassProcedureRequest;
3936
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.BypassProcedureResponse;
@@ -45,6 +42,13 @@
4542
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ScheduleServerCrashProcedureResponse;
4643
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.UnassignsResponse;
4744

45+
import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException;
46+
47+
import org.apache.yetus.audience.InterfaceAudience;
48+
49+
import org.slf4j.Logger;
50+
import org.slf4j.LoggerFactory;
51+
4852
/**
4953
* Use {@link Connection#getHbck()} to obtain an instance of {@link Hbck} instead of
5054
* constructing an HBaseHbck directly.
@@ -98,15 +102,34 @@ public boolean isAborted() {
98102
public TableState setTableStateInMeta(TableState state) throws IOException {
99103
try {
100104
GetTableStateResponse response = hbck.setTableStateInMeta(
101-
rpcControllerFactory.newController(),
102-
RequestConverter.buildSetTableStateInMetaRequest(state));
105+
rpcControllerFactory.newController(),
106+
RequestConverter.buildSetTableStateInMetaRequest(state));
103107
return TableState.convert(state.getTableName(), response.getTableState());
104108
} catch (ServiceException se) {
105109
LOG.debug("table={}, state={}", state.getTableName(), state.getState(), se);
106110
throw new IOException(se);
107111
}
108112
}
109113

114+
@Override
115+
public List<RegionState> setRegionStateInMeta(List<RegionState> states) throws IOException {
116+
try {
117+
if(LOG.isDebugEnabled()) {
118+
states.forEach(s ->
119+
LOG.debug("region={}, state={}", s.getRegion().getRegionName(), s.getState())
120+
);
121+
}
122+
MasterProtos.GetRegionStateInMetaResponse response = hbck.setRegionStateInMeta(
123+
rpcControllerFactory.newController(),
124+
RequestConverter.buildSetRegionStateInMetaRequest(states));
125+
final List<RegionState> result = new ArrayList<>();
126+
response.getStatesList().forEach(s -> result.add(RegionState.convert(s)));
127+
return result;
128+
} catch (ServiceException se) {
129+
throw new IOException(se);
130+
}
131+
}
132+
110133
@Override
111134
public List<Long> assigns(List<String> encodedRegionNames, boolean override)
112135
throws IOException {

hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
2828
import org.apache.hadoop.hbase.ServerName;
2929
import org.apache.hadoop.hbase.TableName;
30+
import org.apache.hadoop.hbase.master.RegionState;
3031
import org.apache.yetus.audience.InterfaceAudience;
3132

3233
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
@@ -54,6 +55,14 @@ public interface Hbck extends Abortable, Closeable {
5455
*/
5556
TableState setTableStateInMeta(TableState state) throws IOException;
5657

58+
/**
59+
* Update region state in Meta only. No procedures are submitted to manipulate the given region
60+
* or any other region from same table.
61+
* @param states list of all region states to be updated in meta
62+
* @return previous state of the region in Meta
63+
*/
64+
List<RegionState> setRegionStateInMeta(List<RegionState> states) throws IOException;
65+
5766
/**
5867
* Like {@link Admin#assign(byte[])} but 'raw' in that it can do more than one Region at a time
5968
* -- good if many Regions to online -- and it will schedule the assigns even in the case where

hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionInfoBuilder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ public RegionInfoBuilder setOffline(boolean offLine) {
116116
return this;
117117
}
118118

119+
public RegionInfoBuilder setEncodedName(String encodedName) {
120+
this.encodedName = encodedName;
121+
return this;
122+
}
123+
119124
public RegionInfo build() {
120125
return new MutableRegionInfo(tableName, startKey, endKey, split,
121126
regionId, replicaId, offLine, regionName, encodedName);

hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,6 +2226,14 @@ public static HBaseProtos.TableName toProtoTableName(TableName tableName) {
22262226
.setQualifier(UnsafeByteOperations.unsafeWrap(tableName.getQualifier())).build();
22272227
}
22282228

2229+
public static HBaseProtos.RegionInfo toProtoRegionInfo(
2230+
org.apache.hadoop.hbase.client.RegionInfo regionInfo) {
2231+
return HBaseProtos.RegionInfo.newBuilder()
2232+
.setRegionId(regionInfo.getRegionId())
2233+
.setRegionEncodedName(regionInfo.getEncodedName())
2234+
.setTableName(toProtoTableName(regionInfo.getTable())).build();
2235+
}
2236+
22292237
public static List<TableName> toTableNameList(List<HBaseProtos.TableName> tableNamesList) {
22302238
if (tableNamesList == null) {
22312239
return new ArrayList<>();
@@ -3145,6 +3153,7 @@ public static HBaseProtos.RegionInfo toRegionInfo(final org.apache.hadoop.hbase.
31453153
builder.setOffline(info.isOffline());
31463154
builder.setSplit(info.isSplit());
31473155
builder.setReplicaId(info.getReplicaId());
3156+
builder.setRegionEncodedName(info.getEncodedName());
31483157
return builder.build();
31493158
}
31503159

@@ -3184,6 +3193,9 @@ public static org.apache.hadoop.hbase.client.RegionInfo toRegionInfo(final HBase
31843193
if (proto.hasOffline()) {
31853194
rib.setOffline(proto.getOffline());
31863195
}
3196+
if (proto.hasRegionEncodedName()) {
3197+
rib.setEncodedName(proto.getRegionEncodedName());
3198+
}
31873199
return rib.build();
31883200
}
31893201

hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.apache.hadoop.hbase.exceptions.DeserializationException;
5656
import org.apache.hadoop.hbase.filter.ByteArrayComparable;
5757
import org.apache.hadoop.hbase.io.TimeRange;
58+
import org.apache.hadoop.hbase.master.RegionState;
5859
import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
5960
import org.apache.hadoop.hbase.replication.SyncReplicationState;
6061
import org.apache.hadoop.hbase.util.Bytes;
@@ -132,6 +133,7 @@
132133
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
133134
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetCleanerChoreRunningRequest;
134135
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormalizerRunningRequest;
136+
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetRegionStateInMetaRequest;
135137
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos
136138
.SetSnapshotCleanupRequest;
137139
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSplitOrMergeEnabledRequest;
@@ -1258,6 +1260,18 @@ public static SetTableStateInMetaRequest buildSetTableStateInMetaRequest(final T
12581260
.setTableName(ProtobufUtil.toProtoTableName(state.getTableName())).build();
12591261
}
12601262

1263+
/**
1264+
* Creates a protocol buffer SetRegionStateInMetaRequest
1265+
* @param states list of regions states to update in Meta
1266+
* @return a SetRegionStateInMetaRequest
1267+
*/
1268+
public static SetRegionStateInMetaRequest buildSetRegionStateInMetaRequest(
1269+
final List<RegionState> states) {
1270+
final SetRegionStateInMetaRequest.Builder builder = SetRegionStateInMetaRequest.newBuilder();
1271+
states.forEach(s -> builder.addStates(s.convert()));
1272+
return builder.build();
1273+
}
1274+
12611275
/**
12621276
* Creates a protocol buffer GetTableDescriptorsRequest for a single table
12631277
*

hbase-protocol-shaded/src/main/protobuf/HBase.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ message RegionInfo {
7979
optional bool offline = 5;
8080
optional bool split = 6;
8181
optional int32 replica_id = 7 [default = 0];
82+
optional string region_encoded_name = 8;
8283
}
8384

8485
/**

hbase-protocol-shaded/src/main/protobuf/Master.proto

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,10 @@ message GetTableStateResponse {
517517
required TableState table_state = 1;
518518
}
519519

520+
message GetRegionStateInMetaResponse {
521+
repeated RegionState states = 1;
522+
}
523+
520524

521525
message GetClusterStatusRequest {
522526
repeated Option options = 1;
@@ -1090,6 +1094,10 @@ message SetTableStateInMetaRequest {
10901094
required TableState table_state = 2;
10911095
}
10921096

1097+
message SetRegionStateInMetaRequest {
1098+
repeated RegionState states = 2;
1099+
}
1100+
10931101
/** Like Admin's AssignRegionRequest except it can
10941102
* take one or more Regions at a time.
10951103
*/
@@ -1152,6 +1160,10 @@ service HbckService {
11521160
rpc SetTableStateInMeta(SetTableStateInMetaRequest)
11531161
returns(GetTableStateResponse);
11541162

1163+
/** Update state of the region in meta only*/
1164+
rpc SetRegionStateInMeta(SetRegionStateInMetaRequest)
1165+
returns(GetRegionStateInMetaResponse);
1166+
11551167
/**
11561168
* Assign regions.
11571169
* Like Admin's assign but works even if the

hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.apache.hadoop.hbase.UnknownRegionException;
4949
import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
5050
import org.apache.hadoop.hbase.client.MasterSwitchType;
51+
import org.apache.hadoop.hbase.client.Put;
5152
import org.apache.hadoop.hbase.client.RegionInfo;
5253
import org.apache.hadoop.hbase.client.RegionInfoBuilder;
5354
import org.apache.hadoop.hbase.client.Table;
@@ -197,6 +198,7 @@
197198
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProcedureResultResponse;
198199
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProceduresRequest;
199200
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProceduresResponse;
201+
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetRegionStateInMetaResponse;
200202
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest;
201203
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetSchemaAlterStatusResponse;
202204
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
@@ -276,6 +278,7 @@
276278
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormalizerRunningResponse;
277279
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRequest;
278280
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaResponse;
281+
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetRegionStateInMetaRequest;
279282
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos
280283
.SetSnapshotCleanupRequest;
281284
import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos
@@ -2465,6 +2468,42 @@ public GetTableStateResponse setTableStateInMeta(RpcController controller,
24652468
}
24662469
}
24672470

2471+
/**
2472+
* Update state of the region in meta only. This is required by hbck in some situations to cleanup
2473+
* stuck assign/ unassign regions procedures for the table.
2474+
*
2475+
* @return previous states of the regions
2476+
*/
2477+
@Override
2478+
public GetRegionStateInMetaResponse setRegionStateInMeta(RpcController controller,
2479+
SetRegionStateInMetaRequest request) throws ServiceException {
2480+
final GetRegionStateInMetaResponse.Builder builder = GetRegionStateInMetaResponse.newBuilder();
2481+
for(ClusterStatusProtos.RegionState s : request.getStatesList()) {
2482+
try {
2483+
RegionInfo info = this.master.getAssignmentManager().
2484+
loadRegionFromMeta(s.getRegionInfo().getRegionEncodedName());
2485+
LOG.trace("region info loaded from meta table: {}", info);
2486+
RegionState prevState = this.master.getAssignmentManager().getRegionStates().
2487+
getRegionState(info);
2488+
RegionState newState = RegionState.convert(s);
2489+
LOG.info("{} set region={} state from {} to {}", master.getClientIdAuditPrefix(), info,
2490+
prevState.getState(), newState.getState());
2491+
Put metaPut = MetaTableAccessor.makePutFromRegionInfo(info, System.currentTimeMillis());
2492+
metaPut.addColumn(HConstants.CATALOG_FAMILY, HConstants.STATE_QUALIFIER,
2493+
Bytes.toBytes(newState.getState().name()));
2494+
List<Put> putList = new ArrayList<>();
2495+
putList.add(metaPut);
2496+
MetaTableAccessor.putsToMetaTable(this.master.getConnection(), putList);
2497+
//Loads from meta again to refresh AM cache with the new region state
2498+
this.master.getAssignmentManager().loadRegionFromMeta(info.getEncodedName());
2499+
builder.addStates(prevState.convert());
2500+
} catch (Exception e) {
2501+
throw new ServiceException(e);
2502+
}
2503+
}
2504+
return builder.build();
2505+
}
2506+
24682507
/**
24692508
* Get RegionInfo from Master using content of RegionSpecifier as key.
24702509
* @return RegionInfo found by decoding <code>rs</code> or null if none found
@@ -2834,4 +2873,5 @@ private boolean shouldSubmitSCP(ServerName serverName) {
28342873
}
28352874
return true;
28362875
}
2876+
28372877
}

hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
import static org.junit.Assert.assertTrue;
2222

2323
import java.io.IOException;
24+
import java.util.ArrayList;
2425
import java.util.Arrays;
26+
import java.util.HashMap;
2527
import java.util.List;
28+
import java.util.Map;
2629
import java.util.Optional;
2730
import java.util.concurrent.CountDownLatch;
2831
import java.util.stream.Collectors;
@@ -38,6 +41,7 @@
3841
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
3942
import org.apache.hadoop.hbase.master.HMaster;
4043
import org.apache.hadoop.hbase.master.RegionState;
44+
import org.apache.hadoop.hbase.master.assignment.AssignmentManager;
4145
import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
4246
import org.apache.hadoop.hbase.master.procedure.TableProcedureInterface;
4347
import org.apache.hadoop.hbase.procedure2.Procedure;
@@ -48,6 +52,7 @@
4852
import org.apache.hadoop.hbase.testclassification.ClientTests;
4953
import org.apache.hadoop.hbase.testclassification.LargeTests;
5054
import org.apache.hadoop.hbase.util.Bytes;
55+
import org.apache.hadoop.hbase.util.Pair;
5156
import org.junit.AfterClass;
5257
import org.junit.Before;
5358
import org.junit.BeforeClass;
@@ -182,6 +187,36 @@ public void testSetTableStateInMeta() throws Exception {
182187
prevState.isDisabled());
183188
}
184189

190+
@Test
191+
public void testSetRegionStateInMeta() throws Exception {
192+
Hbck hbck = getHbck();
193+
try(Admin admin = TEST_UTIL.getAdmin()){
194+
final List<RegionInfo> regions = admin.getRegions(TABLE_NAME);
195+
final AssignmentManager am = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager();
196+
final List<RegionState> prevStates = new ArrayList<>();
197+
final List<RegionState> newStates = new ArrayList<>();
198+
final Map<String, Pair<RegionState, RegionState>> regionsMap = new HashMap<>();
199+
regions.forEach(r -> {
200+
RegionState prevState = am.getRegionStates().getRegionState(r);
201+
prevStates.add(prevState);
202+
RegionState newState = RegionState.createForTesting(r, RegionState.State.CLOSED);
203+
newStates.add(newState);
204+
regionsMap.put(r.getEncodedName(), new Pair<>(prevState, newState));
205+
});
206+
final List<RegionState> result = hbck.setRegionStateInMeta(newStates);
207+
result.forEach(r -> {
208+
RegionState prevState = regionsMap.get(r.getRegion().getEncodedName()).getFirst();
209+
assertEquals(prevState.getState(), r.getState());
210+
});
211+
regions.forEach(r -> {
212+
RegionState cachedState = am.getRegionStates().getRegionState(r.getEncodedName());
213+
RegionState newState = regionsMap.get(r.getEncodedName()).getSecond();
214+
assertEquals(newState.getState(), cachedState.getState());
215+
});
216+
hbck.setRegionStateInMeta(prevStates);
217+
}
218+
}
219+
185220
@Test
186221
public void testAssigns() throws Exception {
187222
Hbck hbck = getHbck();

0 commit comments

Comments
 (0)