Search in sources :

Example 6 with RaftSession

use of io.atomix.protocols.raft.session.RaftSession in project atomix by atomix.

the class RaftServiceManager method applyCloseSession.

/**
 * Applies a close session entry to the state machine.
 */
private void applyCloseSession(Indexed<CloseSessionEntry> entry) {
    RaftSession session = raft.getSessions().getSession(entry.entry().session());
    // If the server session is null, the session either never existed or already expired.
    if (session == null) {
        throw new RaftException.UnknownSession("Unknown session: " + entry.entry().session());
    }
    // Get the state machine executor associated with the session and unregister the session.
    RaftServiceContext service = session.getService();
    service.closeSession(entry.index(), entry.entry().timestamp(), session, entry.entry().expired());
}
Also used : RaftSession(io.atomix.protocols.raft.session.RaftSession) RaftServiceContext(io.atomix.protocols.raft.service.RaftServiceContext)

Example 7 with RaftSession

use of io.atomix.protocols.raft.session.RaftSession in project atomix by atomix.

the class RaftServiceManager method applyMetadata.

/**
 * Applies a metadata entry to the state machine.
 */
private MetadataResult applyMetadata(Indexed<MetadataEntry> entry) {
    // If the session ID is non-zero, read the metadata for the associated state machine.
    if (entry.entry().session() > 0) {
        RaftSession session = raft.getSessions().getSession(entry.entry().session());
        // If the session is null, return an UnknownSessionException.
        if (session == null) {
            logger.warn("Unknown session: " + entry.entry().session());
            throw new RaftException.UnknownSession("Unknown session: " + entry.entry().session());
        }
        Set<SessionMetadata> sessions = new HashSet<>();
        for (RaftSession s : raft.getSessions().getSessions()) {
            if (s.serviceName().equals(session.serviceName())) {
                sessions.add(new SessionMetadata(s.sessionId().id(), s.serviceName(), s.serviceType().id()));
            }
        }
        return new MetadataResult(sessions);
    } else {
        Set<SessionMetadata> sessions = new HashSet<>();
        for (RaftSession session : raft.getSessions().getSessions()) {
            sessions.add(new SessionMetadata(session.sessionId().id(), session.serviceName(), session.serviceType().id()));
        }
        return new MetadataResult(sessions);
    }
}
Also used : RaftSession(io.atomix.protocols.raft.session.RaftSession) SessionMetadata(io.atomix.primitive.session.SessionMetadata) HashSet(java.util.HashSet)

Example 8 with RaftSession

use of io.atomix.protocols.raft.session.RaftSession in project atomix by atomix.

the class RaftServiceManager method applyOpenSession.

/**
 * Applies an open session entry to the state machine.
 */
private long applyOpenSession(Indexed<OpenSessionEntry> entry) {
    PrimitiveType primitiveType = raft.getPrimitiveTypes().get(entry.entry().serviceType());
    if (primitiveType == null) {
        throw new RaftException.UnknownService("Unknown service type " + entry.entry().serviceType());
    }
    // Get the state machine executor or create one if it doesn't already exist.
    RaftServiceContext service = getOrInitializeService(PrimitiveId.from(entry.index()), raft.getPrimitiveTypes().get(entry.entry().serviceType()), entry.entry().serviceName());
    if (service == null) {
        throw new RaftException.UnknownService("Unknown service type " + entry.entry().serviceType());
    }
    SessionId sessionId = SessionId.from(entry.index());
    RaftSession session = raft.getSessions().addSession(new RaftSession(sessionId, NodeId.from(entry.entry().memberId()), entry.entry().serviceName(), primitiveType, entry.entry().readConsistency(), entry.entry().minTimeout(), entry.entry().maxTimeout(), entry.entry().timestamp(), service, raft, threadContextFactory));
    return service.openSession(entry.index(), entry.entry().timestamp(), session);
}
Also used : RaftSession(io.atomix.protocols.raft.session.RaftSession) RaftServiceContext(io.atomix.protocols.raft.service.RaftServiceContext) PrimitiveType(io.atomix.primitive.PrimitiveType) SessionId(io.atomix.primitive.session.SessionId)

Example 9 with RaftSession

use of io.atomix.protocols.raft.session.RaftSession in project atomix by atomix.

the class RaftServiceManager method applyCommand.

/**
 * Applies a command entry to the state machine.
 * <p>
 * Command entries result in commands being executed on the user provided {@link PrimitiveService} and a
 * response being sent back to the client by completing the returned future. All command responses are
 * cached in the command's {@link RaftSession} for fault tolerance. In the event that the same command
 * is applied to the state machine more than once, the original response will be returned.
 * <p>
 * Command entries are written with a sequence number. The sequence number is used to ensure that
 * commands are applied to the state machine in sequential order. If a command entry has a sequence
 * number that is less than the next sequence number for the session, that indicates that it is a
 * duplicate of a command that was already applied. Otherwise, commands are assumed to have been
 * received in sequential order. The reason for this assumption is because leaders always sequence
 * commands as they're written to the log, so no sequence number will be skipped.
 */
private OperationResult applyCommand(Indexed<CommandEntry> entry) {
    // First check to ensure that the session exists.
    RaftSession session = raft.getSessions().getSession(entry.entry().session());
    // to log warnings here.
    if (session == null) {
        logger.debug("Unknown session: " + entry.entry().session());
        throw new RaftException.UnknownSession("unknown session: " + entry.entry().session());
    }
    // Increment the load counter to avoid snapshotting under high load.
    raft.getLoadMonitor().recordEvent();
    // Execute the command using the state machine associated with the session.
    return session.getService().executeCommand(entry.index(), entry.entry().sequenceNumber(), entry.entry().timestamp(), session, entry.entry().operation());
}
Also used : RaftSession(io.atomix.protocols.raft.session.RaftSession)

Example 10 with RaftSession

use of io.atomix.protocols.raft.session.RaftSession in project atomix by atomix.

the class LeaderRole method onQuery.

@Override
public CompletableFuture<QueryResponse> onQuery(final QueryRequest request) {
    raft.checkThread();
    logRequest(request);
    // doesn't exist if the follower hasn't had a chance to see the session's registration entry.
    if (raft.getLastApplied() < request.session()) {
        return CompletableFuture.completedFuture(logResponse(QueryResponse.builder().withStatus(RaftResponse.Status.ERROR).withError(RaftError.Type.UNKNOWN_SESSION, "Session has not yet been created. You're seeing into the future!").build()));
    }
    // Look up the client's session.
    RaftSession session = raft.getSessions().getSession(request.session());
    if (session == null) {
        log.warn("Unknown session {}", request.session());
        return CompletableFuture.completedFuture(logResponse(QueryResponse.builder().withStatus(RaftResponse.Status.ERROR).withError(RaftError.Type.UNKNOWN_SESSION).build()));
    }
    final Indexed<QueryEntry> entry = new Indexed<>(request.index(), new QueryEntry(raft.getTerm(), System.currentTimeMillis(), request.session(), request.sequenceNumber(), request.operation()), 0);
    final CompletableFuture<QueryResponse> future;
    switch(session.readConsistency()) {
        case SEQUENTIAL:
            future = queryLocal(entry);
            break;
        case LINEARIZABLE_LEASE:
            future = queryBoundedLinearizable(entry);
            break;
        case LINEARIZABLE:
            future = queryLinearizable(entry);
            break;
        default:
            future = Futures.exceptionalFuture(new IllegalStateException("Unknown consistency level: " + session.readConsistency()));
            break;
    }
    return future.thenApply(this::logResponse);
}
Also used : QueryEntry(io.atomix.protocols.raft.storage.log.entry.QueryEntry) RaftSession(io.atomix.protocols.raft.session.RaftSession) QueryResponse(io.atomix.protocols.raft.protocol.QueryResponse) Indexed(io.atomix.storage.journal.Indexed)

Aggregations

RaftSession (io.atomix.protocols.raft.session.RaftSession)17 RaftServiceContext (io.atomix.protocols.raft.service.RaftServiceContext)3 PrimitiveType (io.atomix.primitive.PrimitiveType)2 SessionId (io.atomix.primitive.session.SessionId)2 QueryEntry (io.atomix.protocols.raft.storage.log.entry.QueryEntry)2 Indexed (io.atomix.storage.journal.Indexed)2 NodeId (io.atomix.cluster.NodeId)1 SessionMetadata (io.atomix.primitive.session.SessionMetadata)1 ReadConsistency (io.atomix.protocols.raft.ReadConsistency)1 OperationResult (io.atomix.protocols.raft.impl.OperationResult)1 PendingCommand (io.atomix.protocols.raft.impl.PendingCommand)1 RaftContext (io.atomix.protocols.raft.impl.RaftContext)1 RaftServiceManager (io.atomix.protocols.raft.impl.RaftServiceManager)1 CommandResponse (io.atomix.protocols.raft.protocol.CommandResponse)1 QueryResponse (io.atomix.protocols.raft.protocol.QueryResponse)1 RaftServerProtocol (io.atomix.protocols.raft.protocol.RaftServerProtocol)1 TestPrimitiveType (io.atomix.protocols.raft.proxy.impl.TestPrimitiveType)1 RaftSessionRegistry (io.atomix.protocols.raft.session.RaftSessionRegistry)1 ThreadContext (io.atomix.utils.concurrent.ThreadContext)1 ThreadContextFactory (io.atomix.utils.concurrent.ThreadContextFactory)1