Skip to content

Commit bdd2fc6

Browse files
authored
HBASE-22404 Open/Close region request may be executed twice when master restart
1 parent 7878389 commit bdd2fc6

File tree

16 files changed

+159
-54
lines changed

16 files changed

+159
-54
lines changed

hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/RemoteProcedureDispatcher.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.lang.Thread.UncaughtExceptionHandler;
2323
import java.util.HashSet;
2424
import java.util.List;
25+
import java.util.Optional;
2526
import java.util.Set;
2627
import java.util.concurrent.ConcurrentHashMap;
2728
import java.util.concurrent.DelayQueue;
@@ -232,8 +233,12 @@ public RemoteProcedure getRemoteProcedure() {
232233
public interface RemoteProcedure<TEnv, TRemote> {
233234
/**
234235
* For building the remote operation.
236+
* May be empty if no need to send remote call. Usually, this means the RemoteProcedure has been
237+
* finished already. This is possible, as we may have already sent the procedure to RS but then
238+
* the rpc connection is broken so the executeProcedures call fails, but the RS does receive the
239+
* procedure and execute it and then report back, before we retry again.
235240
*/
236-
RemoteOperation remoteCallBuild(TEnv env, TRemote remote);
241+
Optional<RemoteOperation> remoteCallBuild(TEnv env, TRemote remote);
237242

238243
/**
239244
* Called when the executeProcedure call is failed.
@@ -277,8 +282,8 @@ protected ArrayListMultimap<Class<?>, RemoteOperation> buildAndGroupRequestByTyp
277282
final TRemote remote, final Set<RemoteProcedure> remoteProcedures) {
278283
final ArrayListMultimap<Class<?>, RemoteOperation> requestByType = ArrayListMultimap.create();
279284
for (RemoteProcedure proc : remoteProcedures) {
280-
RemoteOperation operation = proc.remoteCallBuild(env, remote);
281-
requestByType.put(operation.getClass(), operation);
285+
Optional<RemoteOperation> operation = proc.remoteCallBuild(env, remote);
286+
operation.ifPresent(op -> requestByType.put(op.getClass(), op));
282287
}
283288
return requestByType;
284289
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
package org.apache.hadoop.hbase.master.assignment;
1919

2020
import java.io.IOException;
21+
import java.util.Optional;
22+
2123
import org.apache.hadoop.hbase.ServerName;
2224
import org.apache.hadoop.hbase.exceptions.UnexpectedStateException;
2325
import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
@@ -117,9 +119,9 @@ protected void reportTransition(final MasterProcedureEnv env, final RegionStateN
117119
}
118120

119121
@Override
120-
public RemoteOperation remoteCallBuild(final MasterProcedureEnv env,
122+
public Optional<RemoteOperation> remoteCallBuild(final MasterProcedureEnv env,
121123
final ServerName serverName) {
122-
return null;
124+
return Optional.empty();
123125
}
124126

125127
@Override

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public TableOperationType getTableOperationType() {
6161
}
6262

6363
@Override
64-
public RemoteOperation remoteCallBuild(MasterProcedureEnv env, ServerName remote) {
64+
public RemoteOperation newRemoteOperation() {
6565
return new RegionCloseOperation(this, region, getProcId(), assignCandidate);
6666
}
6767

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public TableOperationType getTableOperationType() {
5757
}
5858

5959
@Override
60-
public RemoteOperation remoteCallBuild(MasterProcedureEnv env, ServerName remote) {
60+
public RemoteOperation newRemoteOperation() {
6161
return new RegionOpenOperation(this, region, getProcId());
6262
}
6363

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
package org.apache.hadoop.hbase.master.assignment;
1919

2020
import java.io.IOException;
21+
import java.util.Optional;
22+
2123
import org.apache.hadoop.hbase.HConstants;
2224
import org.apache.hadoop.hbase.ServerName;
2325
import org.apache.hadoop.hbase.TableName;
@@ -32,6 +34,7 @@
3234
import org.apache.hadoop.hbase.procedure2.ProcedureSuspendedException;
3335
import org.apache.hadoop.hbase.procedure2.ProcedureUtil;
3436
import org.apache.hadoop.hbase.procedure2.ProcedureYieldException;
37+
import org.apache.hadoop.hbase.procedure2.RemoteProcedureDispatcher;
3538
import org.apache.hadoop.hbase.procedure2.RemoteProcedureDispatcher.RemoteProcedure;
3639
import org.apache.hadoop.hbase.procedure2.RemoteProcedureException;
3740
import org.apache.hadoop.hbase.util.RetryCounter;
@@ -81,6 +84,19 @@ protected RegionRemoteProcedureBase(TransitRegionStateProcedure parent, RegionIn
8184
parent.attachRemoteProc(this);
8285
}
8386

87+
@Override
88+
public Optional<RemoteProcedureDispatcher.RemoteOperation> remoteCallBuild(MasterProcedureEnv env,
89+
ServerName remote) {
90+
// REPORT_SUCCEED means that this remote open/close request already executed in RegionServer.
91+
// So return empty operation and RSProcedureDispatcher no need to send it again.
92+
if (state == RegionRemoteProcedureBaseState.REGION_REMOTE_PROCEDURE_REPORT_SUCCEED) {
93+
return Optional.empty();
94+
}
95+
return Optional.of(newRemoteOperation());
96+
}
97+
98+
protected abstract RemoteProcedureDispatcher.RemoteOperation newRemoteOperation();
99+
84100
@Override
85101
public void remoteOperationCompleted(MasterProcedureEnv env) {
86102
// should not be called since we use reportRegionStateTransition to report the result

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.hadoop.hbase.master.assignment;
1919

2020
import java.io.IOException;
21+
import java.util.Optional;
2122
import java.util.concurrent.atomic.AtomicBoolean;
2223
import org.apache.hadoop.hbase.ServerName;
2324
import org.apache.hadoop.hbase.TableName;
@@ -124,7 +125,8 @@ protected abstract void reportTransition(MasterProcedureEnv env, RegionStateNode
124125
TransitionCode code, long seqId) throws UnexpectedStateException;
125126

126127
@Override
127-
public abstract RemoteOperation remoteCallBuild(MasterProcedureEnv env, ServerName serverName);
128+
public abstract Optional<RemoteOperation> remoteCallBuild(MasterProcedureEnv env,
129+
ServerName serverName);
128130

129131
protected abstract boolean remoteCallFailed(MasterProcedureEnv env, RegionStateNode regionNode,
130132
IOException exception);

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
package org.apache.hadoop.hbase.master.assignment;
2121

2222
import java.io.IOException;
23+
import java.util.Optional;
24+
2325
import org.apache.hadoop.hbase.ServerName;
2426
import org.apache.hadoop.hbase.exceptions.UnexpectedStateException;
2527
import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
@@ -126,9 +128,9 @@ protected void finishTransition(final MasterProcedureEnv env, final RegionStateN
126128
}
127129

128130
@Override
129-
public RemoteOperation remoteCallBuild(final MasterProcedureEnv env,
131+
public Optional<RemoteOperation> remoteCallBuild(final MasterProcedureEnv env,
130132
final ServerName serverName) {
131-
return null;
133+
return Optional.empty();
132134
}
133135

134136
@Override

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.hadoop.hbase.master.procedure;
2020

2121
import java.io.IOException;
22+
import java.util.Optional;
2223

2324
import org.apache.hadoop.fs.Path;
2425
import org.apache.hadoop.hbase.DoNotRetryIOException;
@@ -84,11 +85,12 @@ protected void deserializeStateData(ProcedureStateSerializer serializer) throws
8485
}
8586

8687
@Override
87-
public RemoteProcedureDispatcher.RemoteOperation remoteCallBuild(MasterProcedureEnv env,
88+
public Optional<RemoteProcedureDispatcher.RemoteOperation> remoteCallBuild(MasterProcedureEnv env,
8889
ServerName serverName) {
89-
return new RSProcedureDispatcher.ServerOperation(this, getProcId(), SplitWALCallable.class,
90-
MasterProcedureProtos.SplitWALParameter.newBuilder().setWalPath(walPath).build()
91-
.toByteArray());
90+
return Optional
91+
.of(new RSProcedureDispatcher.ServerOperation(this, getProcId(), SplitWALCallable.class,
92+
MasterProcedureProtos.SplitWALParameter.newBuilder().setWalPath(walPath).build()
93+
.toByteArray()));
9294
}
9395

9496
@Override

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.hadoop.hbase.master.procedure;
1919

2020
import java.io.IOException;
21+
import java.util.Optional;
2122

2223
import org.apache.hadoop.hbase.ServerName;
2324
import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer;
@@ -74,15 +75,13 @@ protected void deserializeStateData(ProcedureStateSerializer serializer) throws
7475
}
7576

7677
@Override
77-
public RemoteProcedureDispatcher.RemoteOperation
78-
remoteCallBuild(MasterProcedureEnv masterProcedureEnv, ServerName remote) {
78+
public Optional<RemoteProcedureDispatcher.RemoteOperation> remoteCallBuild(
79+
MasterProcedureEnv masterProcedureEnv, ServerName remote) {
7980
assert targetServer.equals(remote);
80-
return new RSProcedureDispatcher.ServerOperation(this, getProcId(),
81-
SwitchRpcThrottleRemoteCallable.class,
82-
SwitchRpcThrottleRemoteStateData.newBuilder()
83-
.setTargetServer(ProtobufUtil.toServerName(remote))
84-
.setRpcThrottleEnabled(rpcThrottleEnabled).build()
85-
.toByteArray());
81+
return Optional.of(new RSProcedureDispatcher.ServerOperation(this, getProcId(),
82+
SwitchRpcThrottleRemoteCallable.class, SwitchRpcThrottleRemoteStateData.newBuilder()
83+
.setTargetServer(ProtobufUtil.toServerName(remote))
84+
.setRpcThrottleEnabled(rpcThrottleEnabled).build().toByteArray()));
8685
}
8786

8887
@Override

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
package org.apache.hadoop.hbase.master.replication;
1919

2020
import java.io.IOException;
21+
import java.util.Optional;
22+
2123
import org.apache.hadoop.hbase.ServerName;
2224
import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
2325
import org.apache.hadoop.hbase.master.procedure.PeerProcedureInterface;
@@ -112,12 +114,12 @@ private static PeerOperationType toPeerOperationType(PeerModificationType type)
112114
}
113115

114116
@Override
115-
public RemoteOperation remoteCallBuild(MasterProcedureEnv env, ServerName remote) {
117+
public Optional<RemoteOperation> remoteCallBuild(MasterProcedureEnv env, ServerName remote) {
116118
assert targetServer.equals(remote);
117-
return new ServerOperation(this, getProcId(), RefreshPeerCallable.class,
119+
return Optional.of(new ServerOperation(this, getProcId(), RefreshPeerCallable.class,
118120
RefreshPeerParameter.newBuilder().setPeerId(peerId).setType(toPeerModificationType(type))
119121
.setTargetServer(ProtobufUtil.toServerName(remote)).setStage(stage).build()
120-
.toByteArray());
122+
.toByteArray()));
121123
}
122124

123125
@Override

0 commit comments

Comments
 (0)