X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-akka-raft%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fraft%2FFollowerLogInformationImpl.java;h=883bfbb4e4184f0cbf0843002dfa3498ca13f622;hp=5bf37d6534e5b7b38e5664f67b2dbf0d2d86f113;hb=f782b6b1af793cafc89bda53cbb940dd71bc25ba;hpb=3bc363a69d6d48709f7fd741ef018ecd75b8f99b diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java index 5bf37d6534..883bfbb4e4 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java @@ -8,12 +8,20 @@ package org.opendaylight.controller.cluster.raft; +import com.google.common.base.Preconditions; import com.google.common.base.Stopwatch; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.controller.cluster.raft.behaviors.LeaderInstallSnapshotState; +/** + * Implementation of the FollowerLogInformation interface. + * + * @author Moiz Raja + * @author Thomas Pantelis + */ public class FollowerLogInformationImpl implements FollowerLogInformation { - private final String id; - private final Stopwatch stopwatch = Stopwatch.createUnstarted(); private final RaftActorContext context; @@ -28,13 +36,28 @@ public class FollowerLogInformationImpl implements FollowerLogInformation { private short payloadVersion = -1; - private FollowerState state = FollowerState.VOTING; + // Assume the HELIUM_VERSION version initially for backwards compatibility until we obtain the follower's + // actual version via AppendEntriesReply. Although we no longer support the Helium version, a pre-Boron + // follower will not have the version field in AppendEntriesReply so it will be set to 0 which is + // HELIUM_VERSION. + private short raftVersion = RaftVersions.HELIUM_VERSION; + + private final PeerInfo peerInfo; + + private LeaderInstallSnapshotState installSnapshotState; - public FollowerLogInformationImpl(String id, long matchIndex, RaftActorContext context) { - this.id = id; + /** + * Constructs an instance. + * + * @param peerInfo the associated PeerInfo of the follower. + * @param matchIndex the initial match index. + * @param context the RaftActorContext. + */ + public FollowerLogInformationImpl(PeerInfo peerInfo, long matchIndex, RaftActorContext context) { this.nextIndex = context.getCommitIndex(); this.matchIndex = matchIndex; this.context = context; + this.peerInfo = Preconditions.checkNotNull(peerInfo); } @Override @@ -43,13 +66,18 @@ public class FollowerLogInformationImpl implements FollowerLogInformation { } @Override - public long decrNextIndex() { - return nextIndex--; + public boolean decrNextIndex() { + if (nextIndex >= 0) { + nextIndex--; + return true; + } + + return false; } @Override public boolean setNextIndex(long nextIndex) { - if(this.nextIndex != nextIndex) { + if (this.nextIndex != nextIndex) { this.nextIndex = nextIndex; return true; } @@ -58,13 +86,13 @@ public class FollowerLogInformationImpl implements FollowerLogInformation { } @Override - public long incrMatchIndex(){ + public long incrMatchIndex() { return matchIndex++; } @Override public boolean setMatchIndex(long matchIndex) { - if(this.matchIndex != matchIndex) { + if (this.matchIndex != matchIndex) { this.matchIndex = matchIndex; return true; } @@ -74,7 +102,7 @@ public class FollowerLogInformationImpl implements FollowerLogInformation { @Override public String getId() { - return id; + return peerInfo.getId(); } @Override @@ -89,13 +117,13 @@ public class FollowerLogInformationImpl implements FollowerLogInformation { @Override public boolean isFollowerActive() { - if(state == FollowerState.VOTING_NOT_INITIALIZED) { + if (peerInfo.getVotingState() == VotingState.VOTING_NOT_INITIALIZED) { return false; } long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS); - return (stopwatch.isRunning()) && - (elapsed <= context.getConfigParams().getElectionTimeOutInterval().toMillis()); + return stopwatch.isRunning() + && elapsed <= context.getConfigParams().getElectionTimeOutInterval().toMillis(); } @Override @@ -120,25 +148,23 @@ public class FollowerLogInformationImpl implements FollowerLogInformation { @Override public boolean okToReplicate() { - if(state == FollowerState.VOTING_NOT_INITIALIZED) { + if (peerInfo.getVotingState() == VotingState.VOTING_NOT_INITIALIZED) { return false; } // Return false if we are trying to send duplicate data before the heartbeat interval - if(getNextIndex() == lastReplicatedIndex){ - if(lastReplicatedStopwatch.elapsed(TimeUnit.MILLISECONDS) < context.getConfigParams() - .getHeartBeatInterval().toMillis()){ - return false; - } + if (getNextIndex() == lastReplicatedIndex && lastReplicatedStopwatch.elapsed(TimeUnit.MILLISECONDS) + < context.getConfigParams().getHeartBeatInterval().toMillis()) { + return false; } resetLastReplicated(); return true; } - private void resetLastReplicated(){ + private void resetLastReplicated() { lastReplicatedIndex = getNextIndex(); - if(lastReplicatedStopwatch.isRunning()){ + if (lastReplicatedStopwatch.isRunning()) { lastReplicatedStopwatch.reset(); } lastReplicatedStopwatch.start(); @@ -155,25 +181,40 @@ public class FollowerLogInformationImpl implements FollowerLogInformation { } @Override - public boolean canParticipateInConsensus() { - return state == FollowerState.VOTING; + public short getRaftVersion() { + return raftVersion; + } + + @Override + public void setRaftVersion(short raftVersion) { + this.raftVersion = raftVersion; } @Override - public void setFollowerState(FollowerState state) { - this.state = state; + @Nullable + public LeaderInstallSnapshotState getInstallSnapshotState() { + return installSnapshotState; + } + + @Override + public void setLeaderInstallSnapshotState(@Nonnull LeaderInstallSnapshotState state) { + if (this.installSnapshotState == null) { + this.installSnapshotState = Preconditions.checkNotNull(state); + } } @Override - public FollowerState getFollowerState() { - return state; + public void clearLeaderInstallSnapshotState() { + Preconditions.checkState(installSnapshotState != null); + installSnapshotState.close(); + installSnapshotState = null; } @Override public String toString() { - return "FollowerLogInformationImpl [id=" + id + ", nextIndex=" + nextIndex + ", matchIndex=" + matchIndex - + ", lastReplicatedIndex=" + lastReplicatedIndex + ", state=" + state + ", stopwatch=" - + stopwatch.elapsed(TimeUnit.MILLISECONDS) + ", followerTimeoutMillis=" + return "FollowerLogInformationImpl [id=" + getId() + ", nextIndex=" + nextIndex + ", matchIndex=" + matchIndex + + ", lastReplicatedIndex=" + lastReplicatedIndex + ", votingState=" + peerInfo.getVotingState() + + ", stopwatch=" + stopwatch.elapsed(TimeUnit.MILLISECONDS) + ", followerTimeoutMillis=" + context.getConfigParams().getElectionTimeOutInterval().toMillis() + "]"; } }