Search in sources :

Example 1 with RaftServiceContext

use of io.atomix.protocols.raft.service.RaftServiceContext in project atomix by atomix.

the class RaftServiceManager method applyKeepAlive.

/**
 * Applies a session keep alive entry to the state machine.
 * <p>
 * Keep alive entries are applied to the internal state machine to reset the timeout for a specific session.
 * If the session indicated by the KeepAliveEntry is still held in memory, we mark the session as trusted,
 * indicating that the client has committed a keep alive within the required timeout. Additionally, we check
 * all other sessions for expiration based on the timestamp provided by this KeepAliveEntry. Note that sessions
 * are never completely expired via this method. Leaders must explicitly commit an UnregisterEntry to expire
 * a session.
 * <p>
 * When a KeepAliveEntry is committed to the internal state machine, two specific fields provided in the entry
 * are used to update server-side session state. The {@code commandSequence} indicates the highest command for
 * which the session has received a successful response in the proper sequence. By applying the {@code commandSequence}
 * to the server session, we clear command output held in memory up to that point. The {@code eventVersion} indicates
 * the index up to which the client has received event messages in sequence for the session. Applying the
 * {@code eventVersion} to the server-side session results in events up to that index being removed from memory
 * as they were acknowledged by the client. It's essential that both of these fields be applied via entries committed
 * to the Raft log to ensure they're applied on all servers in sequential order.
 * <p>
 * Keep alive entries are retained in the log until the next time the client sends a keep alive entry or until the
 * client's session is expired. This ensures for sessions that have long timeouts, keep alive entries cannot be cleaned
 * from the log before they're replicated to some servers.
 */
private long[] applyKeepAlive(Indexed<KeepAliveEntry> entry) {
    // Store the session/command/event sequence and event index instead of acquiring a reference to the entry.
    long[] sessionIds = entry.entry().sessionIds();
    long[] commandSequences = entry.entry().commandSequenceNumbers();
    long[] eventIndexes = entry.entry().eventIndexes();
    // Iterate through session identifiers and keep sessions alive.
    List<Long> successfulSessionIds = new ArrayList<>(sessionIds.length);
    for (int i = 0; i < sessionIds.length; i++) {
        long sessionId = sessionIds[i];
        long commandSequence = commandSequences[i];
        long eventIndex = eventIndexes[i];
        RaftSession session = raft.getSessions().getSession(sessionId);
        if (session != null) {
            if (session.getService().keepAlive(entry.index(), entry.entry().timestamp(), session, commandSequence, eventIndex)) {
                successfulSessionIds.add(sessionId);
            }
        }
    }
    // Iterate through services and complete keep-alives, causing sessions to be expired if necessary.
    for (RaftServiceContext service : raft.getServices()) {
        service.completeKeepAlive(entry.index(), entry.entry().timestamp());
    }
    return Longs.toArray(successfulSessionIds);
}
Also used : RaftSession(io.atomix.protocols.raft.session.RaftSession) ArrayList(java.util.ArrayList) RaftServiceContext(io.atomix.protocols.raft.service.RaftServiceContext)

Example 2 with RaftServiceContext

use of io.atomix.protocols.raft.service.RaftServiceContext in project atomix by atomix.

the class RaftServiceManager method initializeService.

/**
 * Initializes a new service.
 */
private RaftServiceContext initializeService(PrimitiveId primitiveId, PrimitiveType primitiveType, String serviceName) {
    RaftServiceContext oldService = raft.getServices().getService(serviceName);
    RaftServiceContext service = new RaftServiceContext(primitiveId, serviceName, primitiveType, primitiveType.newService(), raft, threadContextFactory);
    raft.getServices().registerService(service);
    // If a service with this name was already registered, remove all of its sessions.
    if (oldService != null) {
        raft.getSessions().removeSessions(oldService.serviceId());
    }
    return service;
}
Also used : RaftServiceContext(io.atomix.protocols.raft.service.RaftServiceContext)

Example 3 with RaftServiceContext

use of io.atomix.protocols.raft.service.RaftServiceContext 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 4 with RaftServiceContext

use of io.atomix.protocols.raft.service.RaftServiceContext in project atomix by atomix.

the class RaftServiceManager method installService.

/**
 * Restores the service associated with the given snapshot.
 *
 * @param reader the snapshot reader
 */
private void installService(SnapshotReader reader) {
    PrimitiveId primitiveId = PrimitiveId.from(reader.readLong());
    PrimitiveType primitiveType = raft.getPrimitiveTypes().get(reader.readString());
    String serviceName = reader.readString();
    // Get or create the service associated with the snapshot.
    logger.debug("Installing service {} {}", primitiveId, serviceName);
    RaftServiceContext service = initializeService(primitiveId, primitiveType, serviceName);
    if (service != null) {
        service.installSnapshot(reader);
    }
}
Also used : RaftServiceContext(io.atomix.protocols.raft.service.RaftServiceContext) PrimitiveType(io.atomix.primitive.PrimitiveType) PrimitiveId(io.atomix.primitive.PrimitiveId)

Example 5 with RaftServiceContext

use of io.atomix.protocols.raft.service.RaftServiceContext in project atomix by atomix.

the class RaftServiceManager method snapshot.

/**
 * Takes snapshots for the given index.
 *
 * @param index the index for which to take snapshots
 */
private Snapshot snapshot(long index) {
    Snapshot snapshot = raft.getSnapshotStore().newTemporarySnapshot(index, new WallClockTimestamp());
    try (SnapshotWriter writer = snapshot.openWriter()) {
        for (RaftServiceContext service : raft.getServices()) {
            writer.buffer().mark();
            SnapshotWriter serviceWriter = new SnapshotWriter(writer.buffer().writeInt(0).slice(), writer.snapshot());
            snapshotService(serviceWriter, service);
            int length = serviceWriter.buffer().position();
            writer.buffer().reset().writeInt(length).skip(length);
        }
    } catch (Exception e) {
        snapshot.close();
        throw e;
    }
    return snapshot;
}
Also used : Snapshot(io.atomix.protocols.raft.storage.snapshot.Snapshot) WallClockTimestamp(io.atomix.utils.time.WallClockTimestamp) SnapshotWriter(io.atomix.protocols.raft.storage.snapshot.SnapshotWriter) RaftServiceContext(io.atomix.protocols.raft.service.RaftServiceContext) RaftException(io.atomix.protocols.raft.RaftException)

Aggregations

RaftServiceContext (io.atomix.protocols.raft.service.RaftServiceContext)7 RaftSession (io.atomix.protocols.raft.session.RaftSession)3 PrimitiveType (io.atomix.primitive.PrimitiveType)2 PrimitiveId (io.atomix.primitive.PrimitiveId)1 SessionId (io.atomix.primitive.session.SessionId)1 RaftException (io.atomix.protocols.raft.RaftException)1 RaftContext (io.atomix.protocols.raft.impl.RaftContext)1 RaftServiceManager (io.atomix.protocols.raft.impl.RaftServiceManager)1 RaftServerProtocol (io.atomix.protocols.raft.protocol.RaftServerProtocol)1 TestPrimitiveType (io.atomix.protocols.raft.proxy.impl.TestPrimitiveType)1 Snapshot (io.atomix.protocols.raft.storage.snapshot.Snapshot)1 SnapshotWriter (io.atomix.protocols.raft.storage.snapshot.SnapshotWriter)1 ThreadContext (io.atomix.utils.concurrent.ThreadContext)1 ThreadContextFactory (io.atomix.utils.concurrent.ThreadContextFactory)1 WallClockTimestamp (io.atomix.utils.time.WallClockTimestamp)1 ArrayList (java.util.ArrayList)1