Add raftVersion field to AppendEntriesReply 67/33767/6
authorTom Pantelis <tpanteli@brocade.com>
Tue, 26 Jan 2016 15:18:31 +0000 (10:18 -0500)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 12 Feb 2016 01:14:38 +0000 (01:14 +0000)
Added a raftVersion field to AppendEntriesReply and modified
AbstractLeader to store the raftVersion in the FollowerLogInformation.
This will enable sending the appropriate serialized version for
subsequent messages sent to the follower.

The raftVersion in the FollowerLogInformation is initialized to
0 (HELIUM_VERSION) so we assume the oldest version for backwards
compatibility until we get the first AppendEntriesReply with the
follower's actual version.

Since we're adding a new field to AppendEntriesReply this won't break
backwards compatibility as Java serialization handles that. The
raftVersion will be set to 0 if sent from a pre-boron version.

Change-Id: I4519c4f314674840f2578848b2888c3e8467dd21
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformation.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftVersions.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeader.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesReply.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java

index 6618a97f21f0d1b7145abc77171a950d9bf9d1e8..4367a7a151ff729bcac7de25f4fbeaf54b114089 100644 (file)
@@ -108,4 +108,14 @@ public interface FollowerLogInformation {
      * Sets the payload data version of the follower.
      */
     void setPayloadVersion(short payloadVersion);
      * Sets the payload data version of the follower.
      */
     void setPayloadVersion(short payloadVersion);
+
+    /**
+     * @return the raft version of the follower.
+     */
+    short getRaftVersion();
+
+    /**
+     * Sets the raft version of the follower.
+     */
+    void setRaftVersion(short payloadVersion);
 }
 }
index 1c8d5e6e10647bcbac9ad7f55dd247e6f51f94c6..89884462128b10147383350429f979bd1f8744ca 100644 (file)
@@ -27,6 +27,12 @@ public class FollowerLogInformationImpl implements FollowerLogInformation {
 
     private short payloadVersion = -1;
 
 
     private short payloadVersion = -1;
 
+    // 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;
 
     public FollowerLogInformationImpl(PeerInfo peerInfo, long matchIndex, RaftActorContext context) {
     private final PeerInfo peerInfo;
 
     public FollowerLogInformationImpl(PeerInfo peerInfo, long matchIndex, RaftActorContext context) {
@@ -153,6 +159,16 @@ public class FollowerLogInformationImpl implements FollowerLogInformation {
         this.payloadVersion = payloadVersion;
     }
 
         this.payloadVersion = payloadVersion;
     }
 
+    @Override
+    public short getRaftVersion() {
+        return raftVersion;
+    }
+
+    @Override
+    public void setRaftVersion(short raftVersion) {
+        this.raftVersion = raftVersion;
+    }
+
     @Override
     public String toString() {
         return "FollowerLogInformationImpl [id=" + getId() + ", nextIndex=" + nextIndex + ", matchIndex=" + matchIndex
     @Override
     public String toString() {
         return "FollowerLogInformationImpl [id=" + getId() + ", nextIndex=" + nextIndex + ", matchIndex=" + matchIndex
index 4330a4caa01180dce5967c2259e728798e3530f0..9c70cf9c45b1acac5b59ab6f1e9915843b84c5bb 100644 (file)
@@ -13,5 +13,6 @@ package org.opendaylight.controller.cluster.raft;
 public interface RaftVersions {
     short HELIUM_VERSION = 0;
     short LITHIUM_VERSION = 1;
 public interface RaftVersions {
     short HELIUM_VERSION = 0;
     short LITHIUM_VERSION = 1;
-    short CURRENT_VERSION = LITHIUM_VERSION;
+    short BORON_VERSION = 3;
+    short CURRENT_VERSION = BORON_VERSION;
 }
 }
index 2b94eb312b153867361878222001d932ad048d08..7f3589c82fe469b438ea35c76138eca4036db7c8 100644 (file)
@@ -211,6 +211,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior {
 
         followerLogInformation.markFollowerActive();
         followerLogInformation.setPayloadVersion(appendEntriesReply.getPayloadVersion());
 
         followerLogInformation.markFollowerActive();
         followerLogInformation.setPayloadVersion(appendEntriesReply.getPayloadVersion());
+        followerLogInformation.setRaftVersion(appendEntriesReply.getRaftVersion());
 
         boolean updated = false;
         if (appendEntriesReply.isSuccess()) {
 
         boolean updated = false;
         if (appendEntriesReply.isSuccess()) {
index 00a9e6fd7b37781237f0a9d49d600d74fba61485..ffdfaa6a0ed112ce50eb22d881d2731dd7a69978 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.controller.cluster.raft.messages;
 
 
 package org.opendaylight.controller.cluster.raft.messages;
 
+import org.opendaylight.controller.cluster.raft.RaftVersions;
+
 /**
  * Reply for the AppendEntriesRpc message
  */
 /**
  * Reply for the AppendEntriesRpc message
  */
@@ -31,6 +33,8 @@ public class AppendEntriesReply extends AbstractRaftRPC {
 
     private final short payloadVersion;
 
 
     private final short payloadVersion;
 
+    private final short raftVersion = RaftVersions.CURRENT_VERSION;
+
     private final boolean forceInstallSnapshot;
 
     public AppendEntriesReply(String followerId, long term, boolean success, long logLastIndex, long logLastTerm,
     private final boolean forceInstallSnapshot;
 
     public AppendEntriesReply(String followerId, long term, boolean success, long logLastIndex, long logLastTerm,
@@ -70,6 +74,10 @@ public class AppendEntriesReply extends AbstractRaftRPC {
         return payloadVersion;
     }
 
         return payloadVersion;
     }
 
+    public short getRaftVersion() {
+        return raftVersion;
+    }
+
     public boolean isForceInstallSnapshot() {
         return forceInstallSnapshot;
     }
     public boolean isForceInstallSnapshot() {
         return forceInstallSnapshot;
     }
@@ -78,6 +86,6 @@ public class AppendEntriesReply extends AbstractRaftRPC {
     public String toString() {
         return "AppendEntriesReply [term=" + getTerm() + ", success=" + success + ", followerId=" + followerId
                 + ", logLastIndex=" + logLastIndex + ", logLastTerm=" + logLastTerm + ", forceInstallSnapshot="
     public String toString() {
         return "AppendEntriesReply [term=" + getTerm() + ", success=" + success + ", followerId=" + followerId
                 + ", logLastIndex=" + logLastIndex + ", logLastTerm=" + logLastTerm + ", forceInstallSnapshot="
-                + forceInstallSnapshot + ", payloadVersion=" + payloadVersion + "]";
+                + forceInstallSnapshot + ", payloadVersion=" + payloadVersion + ", raftVersion=" + raftVersion + "]";
     }
 }
     }
 }
index 26e5b7bffa320bfae8f098b55bd2c24061c3e127..8529e1926b31ebb88548653594ec867af202b6ea 100644 (file)
@@ -37,6 +37,7 @@ import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorLeadershipTransferCohort;
 import org.opendaylight.controller.cluster.raft.RaftState;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorLeadershipTransferCohort;
 import org.opendaylight.controller.cluster.raft.RaftState;
+import org.opendaylight.controller.cluster.raft.RaftVersions;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry;
 import org.opendaylight.controller.cluster.raft.SerializationUtils;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry;
 import org.opendaylight.controller.cluster.raft.SerializationUtils;
@@ -1658,7 +1659,10 @@ public class LeaderTest extends AbstractLeaderTest {
 
         leader = new Leader(leaderActorContext);
 
 
         leader = new Leader(leaderActorContext);
 
+        FollowerLogInformation followerInfo = leader.getFollower(FOLLOWER_ID);
+
         assertEquals(payloadVersion, leader.getLeaderPayloadVersion());
         assertEquals(payloadVersion, leader.getLeaderPayloadVersion());
+        assertEquals(RaftVersions.HELIUM_VERSION, followerInfo.getRaftVersion());
 
         short payloadVersion = 5;
         AppendEntriesReply reply = new AppendEntriesReply(FOLLOWER_ID, 1, true, 2, 1, payloadVersion);
 
         short payloadVersion = 5;
         AppendEntriesReply reply = new AppendEntriesReply(FOLLOWER_ID, 1, true, 2, 1, payloadVersion);
@@ -1685,8 +1689,10 @@ public class LeaderTest extends AbstractLeaderTest {
 
         assertEquals(2, applyState.getReplicatedLogEntry().getIndex());
 
 
         assertEquals(2, applyState.getReplicatedLogEntry().getIndex());
 
-        FollowerLogInformation followerInfo = leader.getFollower(FOLLOWER_ID);
+        assertEquals(2, followerInfo.getMatchIndex());
+        assertEquals(3, followerInfo.getNextIndex());
         assertEquals(payloadVersion, followerInfo.getPayloadVersion());
         assertEquals(payloadVersion, followerInfo.getPayloadVersion());
+        assertEquals(RaftVersions.CURRENT_VERSION, followerInfo.getRaftVersion());
     }
 
     @Test
     }
 
     @Test