Skip to content

Commit

Permalink
RATIS-2235. Allow only one thread to perform appendLog (#1206)
Browse files Browse the repository at this point in the history
  • Loading branch information
SzyWilliam committed Jan 9, 2025
1 parent 66cd822 commit 722bb3a
Showing 1 changed file with 24 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -249,6 +250,8 @@ public long[] getFollowerNextIndices() {
private final AtomicBoolean firstElectionSinceStartup = new AtomicBoolean(true);
private final ThreadGroup threadGroup;

private final AtomicReference<CompletableFuture<Void>> appendLogFuture;

RaftServerImpl(RaftGroup group, StateMachine stateMachine, RaftServerProxy proxy, RaftStorage.StartupOption option)
throws IOException {
final RaftPeerId id = proxy.getId();
Expand Down Expand Up @@ -282,6 +285,7 @@ public long[] getFollowerNextIndices() {
this.transferLeadership = new TransferLeadership(this, properties);
this.snapshotRequestHandler = new SnapshotManagementRequestHandler(this);
this.snapshotInstallationHandler = new SnapshotInstallationHandler(this, properties);
this.appendLogFuture = new AtomicReference<>(CompletableFuture.completedFuture(null));

this.serverExecutor = ConcurrentUtils.newThreadPoolWithMax(
RaftServerConfigKeys.ThreadPool.serverCached(properties),
Expand Down Expand Up @@ -630,6 +634,15 @@ synchronized void changeToLeader() {

@Override
public Collection<CommitInfoProto> getCommitInfos() {
try {
return getCommitInfosImpl();
} catch (Throwable t) {
LOG.warn("{} Failed to getCommitInfos", getMemberId(), t);
return Collections.emptyList();
}
}

private Collection<CommitInfoProto> getCommitInfosImpl() {
final List<CommitInfoProto> infos = new ArrayList<>();
// add the commit info of this server
final long commitIndex = updateCommitInfoCache();
Expand Down Expand Up @@ -803,8 +816,6 @@ private CompletableFuture<RaftClientReply> appendTransaction(
CodeInjectionForTesting.execute(APPEND_TRANSACTION, getId(),
request.getClientId(), request, context, cacheEntry);

assertLifeCycleState(LifeCycle.States.RUNNING);

final PendingRequest pending;
synchronized (this) {
final CompletableFuture<RaftClientReply> reply = checkLeaderState(request, cacheEntry);
Expand All @@ -823,6 +834,7 @@ private CompletableFuture<RaftClientReply> appendTransaction(
return cacheEntry.getReplyFuture();
}
try {
assertLifeCycleState(LifeCycle.States.RUNNING);
state.appendLog(context);
} catch (StateMachineException e) {
// the StateMachineException is thrown by the SM in the preAppend stage.
Expand All @@ -834,6 +846,9 @@ private CompletableFuture<RaftClientReply> appendTransaction(
leaderState.submitStepDownEvent(LeaderState.StepDownReason.STATE_MACHINE_EXCEPTION);
}
return CompletableFuture.completedFuture(exceptionReply);
} catch (ServerNotReadyException e) {
final RaftClientReply exceptionReply = newExceptionReply(request, e);
return CompletableFuture.completedFuture(exceptionReply);
}

// put the request into the pending queue
Expand Down Expand Up @@ -1585,9 +1600,9 @@ leaderId, getMemberId(), currentTerm, followerCommit, inconsistencyReplyNextInde
state.updateConfiguration(entries);
}
future.join();
final CompletableFuture<Void> appendLog = entries.isEmpty()? CompletableFuture.completedFuture(null)
: appendLog(entries);

final List<CompletableFuture<Long>> futures = entries.isEmpty() ? Collections.emptyList()
: state.getLog().append(entries);
proto.getCommitInfosList().forEach(commitInfoCache::update);

CodeInjectionForTesting.execute(LOG_SYNC, getId(), null);
Expand All @@ -1601,7 +1616,7 @@ leaderId, getMemberId(), currentTerm, followerCommit, inconsistencyReplyNextInde

final long commitIndex = effectiveCommitIndex(proto.getLeaderCommit(), previous, entries.size());
final long matchIndex = isHeartbeat? RaftLog.INVALID_LOG_INDEX: entries.get(entries.size() - 1).getIndex();
return JavaUtils.allOf(futures).whenCompleteAsync((r, t) -> {
return appendLog.whenCompleteAsync((r, t) -> {
followerState.ifPresent(fs -> fs.updateLastRpcTime(FollowerState.UpdateType.APPEND_COMPLETE));
timer.stop();
}, getServerExecutor()).thenApply(v -> {
Expand All @@ -1618,6 +1633,10 @@ leaderId, getMemberId(), currentTerm, followerCommit, inconsistencyReplyNextInde
return reply;
});
}
private CompletableFuture<Void> appendLog(List<LogEntryProto> entries) {
return appendLogFuture.updateAndGet(f -> f.thenCompose(
ignored -> JavaUtils.allOf(state.getLog().append(entries))));
}

private long checkInconsistentAppendEntries(TermIndex previous, List<LogEntryProto> entries) {
// Check if a snapshot installation through state machine is in progress.
Expand Down

0 comments on commit 722bb3a

Please sign in to comment.