use of org.apache.ratis.protocol.exceptions.StateMachineException in project incubator-ratis by apache.
the class RaftServerImpl method submitClientRequestAsync.
@Override
public CompletableFuture<RaftClientReply> submitClientRequestAsync(RaftClientRequest request) throws IOException {
assertLifeCycleState(LifeCycle.States.RUNNING);
LOG.debug("{}: receive client request({})", getMemberId(), request);
final Optional<Timer> timer = Optional.ofNullable(raftServerMetrics.getClientRequestTimer(request.getType()));
final CompletableFuture<RaftClientReply> replyFuture;
if (request.is(TypeCase.STALEREAD)) {
replyFuture = staleReadAsync(request);
} else {
// first check the server's leader state
CompletableFuture<RaftClientReply> reply = checkLeaderState(request, null, !request.is(TypeCase.READ) && !request.is(TypeCase.WATCH));
if (reply != null) {
return reply;
}
// let the state machine handle read-only request from client
RaftClientRequest.Type type = request.getType();
if (type.is(TypeCase.MESSAGESTREAM)) {
if (type.getMessageStream().getEndOfRequest()) {
final CompletableFuture<RaftClientRequest> f = streamEndOfRequestAsync(request);
if (f.isCompletedExceptionally()) {
return f.thenApply(r -> null);
}
request = f.join();
type = request.getType();
}
}
if (type.is(TypeCase.READ)) {
// TODO: We might not be the leader anymore by the time this completes.
// See the RAFT paper section 8 (last part)
replyFuture = processQueryFuture(stateMachine.query(request.getMessage()), request);
} else if (type.is(TypeCase.WATCH)) {
replyFuture = watchAsync(request);
} else if (type.is(TypeCase.MESSAGESTREAM)) {
replyFuture = streamAsync(request);
} else {
// query the retry cache
final RetryCacheImpl.CacheQueryResult queryResult = retryCache.queryCache(ClientInvocationId.valueOf(request));
final CacheEntry cacheEntry = queryResult.getEntry();
if (queryResult.isRetry()) {
// if the previous attempt is still pending or it succeeded, return its
// future
replyFuture = cacheEntry.getReplyFuture();
} else {
// TODO: this client request will not be added to pending requests until
// later which means that any failure in between will leave partial state in
// the state machine. We should call cancelTransaction() for failed requests
TransactionContext context = stateMachine.startTransaction(filterDataStreamRaftClientRequest(request));
if (context.getException() != null) {
final StateMachineException e = new StateMachineException(getMemberId(), context.getException());
final RaftClientReply exceptionReply = newExceptionReply(request, e);
cacheEntry.failWithReply(exceptionReply);
replyFuture = CompletableFuture.completedFuture(exceptionReply);
} else {
replyFuture = appendTransaction(request, context, cacheEntry);
}
}
}
}
final RaftClientRequest.Type type = request.getType();
replyFuture.whenComplete((clientReply, exception) -> {
if (clientReply.isSuccess()) {
timer.map(Timer::time).ifPresent(Timer.Context::stop);
}
if (exception != null || clientReply.getException() != null) {
raftServerMetrics.incFailedRequestCount(type);
}
});
return replyFuture;
}
use of org.apache.ratis.protocol.exceptions.StateMachineException in project incubator-ratis by apache.
the class RaftLogBase method appendImpl.
private long appendImpl(long term, TransactionContext operation) throws StateMachineException {
checkLogState();
try (AutoCloseableLock writeLock = writeLock()) {
final long nextIndex = getNextIndex();
// the SM wants to attach a logic depending on ordered execution in the log commit order.
try {
operation = operation.preAppendTransaction();
} catch (StateMachineException e) {
throw e;
} catch (IOException e) {
throw new StateMachineException(memberId, e);
}
// build the log entry after calling the StateMachine
final LogEntryProto e = operation.initLogEntry(term, nextIndex);
int entrySize = e.getSerializedSize();
if (entrySize > maxBufferSize) {
throw new StateMachineException(memberId, new RaftLogIOException("Log entry size " + entrySize + " exceeds the max buffer limit of " + maxBufferSize));
}
appendEntry(e);
return nextIndex;
}
}
use of org.apache.ratis.protocol.exceptions.StateMachineException in project incubator-ratis by apache.
the class StateMachineUpdater method takeSnapshot.
private void takeSnapshot() {
final long i;
try {
Timer.Context takeSnapshotTimerContext = stateMachineMetrics.getTakeSnapshotTimer().time();
i = stateMachine.takeSnapshot();
takeSnapshotTimerContext.stop();
server.getSnapshotRequestHandler().completeTakingSnapshot(i);
final long lastAppliedIndex = getLastAppliedIndex();
if (i > lastAppliedIndex) {
throw new StateMachineException("Bug in StateMachine: snapshot index = " + i + " > appliedIndex = " + lastAppliedIndex + "; StateMachine class=" + stateMachine.getClass().getName() + ", stateMachine=" + stateMachine);
}
stateMachine.getStateMachineStorage().cleanupOldSnapshots(snapshotRetentionPolicy);
} catch (IOException e) {
LOG.error(name + ": Failed to take snapshot", e);
return;
}
if (i >= 0) {
LOG.info("{}: Took a snapshot at index {}", name, i);
snapshotIndex.updateIncreasingly(i, infoIndexChange);
final long purgeIndex;
if (purgeUptoSnapshotIndex) {
// We can purge up to snapshot index even if all the peers do not have
// commitIndex up to this snapshot index.
purgeIndex = i;
} else {
final LongStream commitIndexStream = server.getCommitInfos().stream().mapToLong(CommitInfoProto::getCommitIndex);
purgeIndex = LongStream.concat(LongStream.of(i), commitIndexStream).min().orElse(i);
}
raftLog.purge(purgeIndex);
}
}
use of org.apache.ratis.protocol.exceptions.StateMachineException in project incubator-ratis by apache.
the class TestNettyDataStreamWithMock method testStateMachineExceptionInReply.
@Test
public void testStateMachineExceptionInReply() throws Exception {
StateMachineException stateMachineException = new StateMachineException("leader throw StateMachineException");
testMockCluster(3, stateMachineException, null);
}
use of org.apache.ratis.protocol.exceptions.StateMachineException in project incubator-ratis by apache.
the class FileStoreClient method sendAsync.
static CompletableFuture<ByteString> sendAsync(ByteString request, Function<Message, CompletableFuture<RaftClientReply>> sendFunction) {
return sendFunction.apply(() -> request).thenApply(reply -> {
final StateMachineException sme = reply.getStateMachineException();
if (sme != null) {
throw new CompletionException("Failed to send request " + request, sme);
}
Preconditions.assertTrue(reply.isSuccess(), () -> "Failed " + request + ", reply=" + reply);
return reply.getMessage().getContent();
});
}
Aggregations