Search in sources :

Example 1 with StateMachineException

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;
}
Also used : TransactionContext(org.apache.ratis.statemachine.TransactionContext) StateMachineException(org.apache.ratis.protocol.exceptions.StateMachineException) CacheEntry(org.apache.ratis.server.impl.RetryCacheImpl.CacheEntry) Timer(com.codahale.metrics.Timer) TransactionContext(org.apache.ratis.statemachine.TransactionContext)

Example 2 with StateMachineException

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;
    }
}
Also used : StateMachineException(org.apache.ratis.protocol.exceptions.StateMachineException) LogEntryProto(org.apache.ratis.proto.RaftProtos.LogEntryProto) AutoCloseableLock(org.apache.ratis.util.AutoCloseableLock) IOException(java.io.IOException)

Example 3 with StateMachineException

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);
    }
}
Also used : StateMachineException(org.apache.ratis.protocol.exceptions.StateMachineException) CommitInfoProto(org.apache.ratis.proto.RaftProtos.CommitInfoProto) Timer(com.codahale.metrics.Timer) RaftLogIOException(org.apache.ratis.server.raftlog.RaftLogIOException) IOException(java.io.IOException) LongStream(java.util.stream.LongStream)

Example 4 with StateMachineException

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);
}
Also used : StateMachineException(org.apache.ratis.protocol.exceptions.StateMachineException) Test(org.junit.Test)

Example 5 with StateMachineException

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();
    });
}
Also used : StateMachineException(org.apache.ratis.protocol.exceptions.StateMachineException) CompletionException(java.util.concurrent.CompletionException)

Aggregations

StateMachineException (org.apache.ratis.protocol.exceptions.StateMachineException)13 IOException (java.io.IOException)5 Timer (com.codahale.metrics.Timer)2 LogEntryProto (org.apache.ratis.proto.RaftProtos.LogEntryProto)2 RaftClientReply (org.apache.ratis.protocol.RaftClientReply)2 AlreadyClosedException (org.apache.ratis.protocol.exceptions.AlreadyClosedException)2 LeaderSteppingDownException (org.apache.ratis.protocol.exceptions.LeaderSteppingDownException)2 TransferLeadershipException (org.apache.ratis.protocol.exceptions.TransferLeadershipException)2 CacheEntry (org.apache.ratis.server.impl.RetryCacheImpl.CacheEntry)2 InterruptedIOException (java.io.InterruptedIOException)1 CompletionException (java.util.concurrent.CompletionException)1 ExecutionException (java.util.concurrent.ExecutionException)1 LongStream (java.util.stream.LongStream)1 RaftTestUtil (org.apache.ratis.RaftTestUtil)1 SimpleMessage (org.apache.ratis.RaftTestUtil.SimpleMessage)1 RaftClient (org.apache.ratis.client.RaftClient)1 ClientRetryEvent (org.apache.ratis.client.retry.ClientRetryEvent)1 CommitInfoProto (org.apache.ratis.proto.RaftProtos.CommitInfoProto)1 RaftClientRequest (org.apache.ratis.protocol.RaftClientRequest)1 AlreadyExistsException (org.apache.ratis.protocol.exceptions.AlreadyExistsException)1