Search in sources :

Example 56 with AppendEntriesReply

use of org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply in project controller by opendaylight.

the class Follower method handleAppendEntries.

@Override
protected RaftActorBehavior handleAppendEntries(final ActorRef sender, final AppendEntries appendEntries) {
    int numLogEntries = appendEntries.getEntries().size();
    if (log.isTraceEnabled()) {
        log.trace("{}: handleAppendEntries: {}", logName(), appendEntries);
    } else if (log.isDebugEnabled() && numLogEntries > 0) {
        log.debug("{}: handleAppendEntries: {}", logName(), appendEntries);
    }
    if (snapshotTracker != null && !snapshotTracker.getLeaderId().equals(appendEntries.getLeaderId())) {
        log.debug("{}: snapshot install is in progress but the prior snapshot leaderId {} does not match the " + "AppendEntries leaderId {}", logName(), snapshotTracker.getLeaderId(), appendEntries.getLeaderId());
        closeSnapshotTracker();
    }
    if (snapshotTracker != null || context.getSnapshotManager().isApplying()) {
        // if snapshot install is in progress, follower should just acknowledge append entries with a reply.
        AppendEntriesReply reply = new AppendEntriesReply(context.getId(), currentTerm(), true, lastIndex(), lastTerm(), context.getPayloadVersion());
        log.debug("{}: snapshot install is in progress, replying immediately with {}", logName(), reply);
        sender.tell(reply, actor());
        return this;
    }
    // If we got here then we do appear to be talking to the leader
    leaderId = appendEntries.getLeaderId();
    leaderPayloadVersion = appendEntries.getPayloadVersion();
    // First check if the logs are in sync or not
    if (isOutOfSync(appendEntries, sender)) {
        updateInitialSyncStatus(appendEntries.getLeaderCommit(), appendEntries.getLeaderId());
        return this;
    }
    if (!processNewEntries(appendEntries, sender)) {
        updateInitialSyncStatus(appendEntries.getLeaderCommit(), appendEntries.getLeaderId());
        return this;
    }
    long lastIndex = lastIndex();
    long prevCommitIndex = context.getCommitIndex();
    // If leaderCommit > commitIndex, set commitIndex = min(leaderCommit, index of last new entry)
    if (appendEntries.getLeaderCommit() > prevCommitIndex) {
        context.setCommitIndex(Math.min(appendEntries.getLeaderCommit(), lastIndex));
    }
    if (prevCommitIndex != context.getCommitIndex()) {
        log.debug("{}: Commit index set to {}", logName(), context.getCommitIndex());
    }
    AppendEntriesReply reply = new AppendEntriesReply(context.getId(), currentTerm(), true, lastIndex, lastTerm(), context.getPayloadVersion());
    if (log.isTraceEnabled()) {
        log.trace("{}: handleAppendEntries returning : {}", logName(), reply);
    } else if (log.isDebugEnabled() && numLogEntries > 0) {
        log.debug("{}: handleAppendEntries returning : {}", logName(), reply);
    }
    // Reply to the leader before applying any previous state so as not to hold up leader consensus.
    sender.tell(reply, actor());
    updateInitialSyncStatus(appendEntries.getLeaderCommit(), appendEntries.getLeaderId());
    // lastApplied can be equal to lastIndex.
    if (appendEntries.getLeaderCommit() > context.getLastApplied() && context.getLastApplied() < lastIndex) {
        if (log.isDebugEnabled()) {
            log.debug("{}: applyLogToStateMachine, appendEntries.getLeaderCommit(): {}, " + "context.getLastApplied(): {}, lastIndex(): {}", logName(), appendEntries.getLeaderCommit(), context.getLastApplied(), lastIndex);
        }
        applyLogToStateMachine(appendEntries.getLeaderCommit());
    }
    if (!context.getSnapshotManager().isCapturing()) {
        super.performSnapshotWithoutCapture(appendEntries.getReplicatedToAllIndex());
    }
    appendEntriesMessageAssembler.checkExpiredAssembledMessageState();
    return this;
}
Also used : AppendEntriesReply(org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply)

Example 57 with AppendEntriesReply

use of org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply in project controller by opendaylight.

the class DummyShard method handleAppendEntries.

protected void handleAppendEntries(AppendEntries req) throws InterruptedException {
    LOG.info("{} - Received AppendEntries message : leader term = {}, index = {}, prevLogIndex = {}, size = {}", followerId, req.getTerm(), req.getLeaderCommit(), req.getPrevLogIndex(), req.getEntries().size());
    if (appendEntriesWatch != null) {
        long elapsed = appendEntriesWatch.elapsed(TimeUnit.SECONDS);
        if (elapsed >= 5) {
            LOG.error("More than 5 seconds since last append entry, elapsed Time = {} seconds" + ", leaderCommit = {}, prevLogIndex = {}, size = {}", elapsed, req.getLeaderCommit(), req.getPrevLogIndex(), req.getEntries().size());
        }
        appendEntriesWatch.reset().start();
    } else {
        appendEntriesWatch = Stopwatch.createStarted();
    }
    if (lastMessageIndex == req.getLeaderCommit() && req.getEntries().size() > 0 && lastMessageSize > 0) {
        LOG.error("{} - Duplicate message with leaderCommit = {} prevLogIndex = {} received", followerId, req.getLeaderCommit(), req.getPrevLogIndex());
    }
    lastMessageIndex = req.getLeaderCommit();
    lastMessageSize = req.getEntries().size();
    long lastIndex = req.getLeaderCommit();
    if (req.getEntries().size() > 0) {
        for (ReplicatedLogEntry entry : req.getEntries()) {
            lastIndex = entry.getIndex();
        }
    }
    if (configuration.shouldCauseTrouble() && req.getEntries().size() > 0) {
        boolean ignore = false;
        if (configuration.shouldDropReplies()) {
            ignore = Math.random() > 0.5;
        }
        long delay = (long) (Math.random() * configuration.getMaxDelayInMillis());
        if (!ignore) {
            LOG.info("{} - Randomizing delay : {}", followerId, delay);
            Thread.sleep(delay);
            sender().tell(new AppendEntriesReply(followerId, req.getTerm(), true, lastIndex, req.getTerm(), DataStoreVersions.CURRENT_VERSION), self());
        }
    } else {
        sender().tell(new AppendEntriesReply(followerId, req.getTerm(), true, lastIndex, req.getTerm(), DataStoreVersions.CURRENT_VERSION), self());
    }
}
Also used : ReplicatedLogEntry(org.opendaylight.controller.cluster.raft.ReplicatedLogEntry) AppendEntriesReply(org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply)

Aggregations

AppendEntriesReply (org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply)57 Test (org.junit.Test)48 MockRaftActorContext (org.opendaylight.controller.cluster.raft.MockRaftActorContext)40 AppendEntries (org.opendaylight.controller.cluster.raft.messages.AppendEntries)34 FiniteDuration (scala.concurrent.duration.FiniteDuration)23 DefaultConfigParamsImpl (org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl)22 SimpleReplicatedLogEntry (org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry)17 ReplicatedLogEntry (org.opendaylight.controller.cluster.raft.ReplicatedLogEntry)15 ByteString (com.google.protobuf.ByteString)13 HashMap (java.util.HashMap)8 ActorRef (akka.actor.ActorRef)7 TestActorRef (akka.testkit.TestActorRef)6 InstallSnapshot (org.opendaylight.controller.cluster.raft.messages.InstallSnapshot)6 FollowerLogInformation (org.opendaylight.controller.cluster.raft.FollowerLogInformation)5 FollowerInitialSyncUpStatus (org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus)5 AtomicReference (java.util.concurrent.atomic.AtomicReference)4 MockPayload (org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload)4 RaftActorLeadershipTransferCohort (org.opendaylight.controller.cluster.raft.RaftActorLeadershipTransferCohort)4 ApplySnapshot (org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot)4 ApplyState (org.opendaylight.controller.cluster.raft.base.messages.ApplyState)4