Make Netty-3 dependency optional
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / main / java / org / opendaylight / controller / cluster / raft / messages / AppendEntriesReply.java
index e2f0ba9014c9e469b21599359db3007e7cb4e2be..033a19a7b26e758a30430b902085649af4c886ef 100644 (file)
@@ -5,9 +5,9 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-
 package org.opendaylight.controller.cluster.raft.messages;
 
+import com.google.common.annotations.VisibleForTesting;
 import java.io.Externalizable;
 import java.io.IOException;
 import java.io.ObjectInput;
@@ -17,7 +17,8 @@ import org.opendaylight.controller.cluster.raft.RaftVersions;
 /**
  * Reply for the AppendEntries message.
  */
-public class AppendEntriesReply extends AbstractRaftRPC {
+public final class AppendEntriesReply extends AbstractRaftRPC {
+    @java.io.Serial
     private static final long serialVersionUID = -7487547356392536683L;
 
     // true if follower contained entry matching
@@ -41,22 +42,28 @@ public class AppendEntriesReply extends AbstractRaftRPC {
 
     private final boolean forceInstallSnapshot;
 
-    public AppendEntriesReply(String followerId, long term, boolean success, long logLastIndex, long logLastTerm,
-            short payloadVersion) {
-        this(followerId, term, success, logLastIndex, logLastTerm, payloadVersion, false);
-    }
+    private final boolean needsLeaderAddress;
 
-    public AppendEntriesReply(String followerId, long term, boolean success, long logLastIndex, long logLastTerm,
-            short payloadVersion, boolean forceInstallSnapshot) {
-        this(followerId, term, success, logLastIndex, logLastTerm, payloadVersion, forceInstallSnapshot,
+    private final short recipientRaftVersion;
+
+    @VisibleForTesting
+    public AppendEntriesReply(final String followerId, final long term, final boolean success, final long logLastIndex,
+            final long logLastTerm, final short payloadVersion) {
+        this(followerId, term, success, logLastIndex, logLastTerm, payloadVersion, false, false,
                 RaftVersions.CURRENT_VERSION);
+    }
 
+    public AppendEntriesReply(final String followerId, final long term, final boolean success, final long logLastIndex,
+            final long logLastTerm, final short payloadVersion, final boolean forceInstallSnapshot,
+            final boolean needsLeaderAddress, final short recipientRaftVersion) {
+        this(followerId, term, success, logLastIndex, logLastTerm, payloadVersion, forceInstallSnapshot,
+                needsLeaderAddress, RaftVersions.CURRENT_VERSION, recipientRaftVersion);
     }
 
-    private AppendEntriesReply(String followerId, long term, boolean success, long logLastIndex, long logLastTerm,
-                              short payloadVersion, boolean forceInstallSnapshot, short raftVersion) {
+    AppendEntriesReply(final String followerId, final long term, final boolean success, final long logLastIndex,
+            final long logLastTerm, final short payloadVersion, final boolean forceInstallSnapshot,
+            final boolean needsLeaderAddress, final short raftVersion, final short recipientRaftVersion) {
         super(term);
-
         this.followerId = followerId;
         this.success = success;
         this.logLastIndex = logLastIndex;
@@ -64,6 +71,8 @@ public class AppendEntriesReply extends AbstractRaftRPC {
         this.payloadVersion = payloadVersion;
         this.forceInstallSnapshot = forceInstallSnapshot;
         this.raftVersion = raftVersion;
+        this.needsLeaderAddress = needsLeaderAddress;
+        this.recipientRaftVersion = recipientRaftVersion;
     }
 
     public boolean isSuccess() {
@@ -94,18 +103,29 @@ public class AppendEntriesReply extends AbstractRaftRPC {
         return forceInstallSnapshot;
     }
 
+    public boolean isNeedsLeaderAddress() {
+        return needsLeaderAddress;
+    }
+
     @Override
     public String toString() {
         return "AppendEntriesReply [term=" + getTerm() + ", success=" + success + ", followerId=" + followerId
                 + ", logLastIndex=" + logLastIndex + ", logLastTerm=" + logLastTerm + ", forceInstallSnapshot="
-                + forceInstallSnapshot + ", payloadVersion=" + payloadVersion + ", raftVersion=" + raftVersion + "]";
+                + forceInstallSnapshot + ", needsLeaderAddress=" + needsLeaderAddress
+                + ", payloadVersion=" + payloadVersion + ", raftVersion=" + raftVersion
+                + ", recipientRaftVersion=" + recipientRaftVersion + "]";
     }
 
-    private Object writeReplace() {
-        return new Proxy(this);
+    @Override
+    Object writeReplace() {
+        return recipientRaftVersion <= RaftVersions.FLUORINE_VERSION ? new Proxy2(this) : new AR(this);
     }
 
-    private static class Proxy implements Externalizable {
+    /**
+     * Fluorine version that adds the needsLeaderAddress flag.
+     */
+    private static class Proxy2 implements Externalizable {
+        @java.io.Serial
         private static final long serialVersionUID = 1L;
 
         private AppendEntriesReply appendEntriesReply;
@@ -113,15 +133,15 @@ public class AppendEntriesReply extends AbstractRaftRPC {
         // checkstyle flags the public modifier as redundant which really doesn't make sense since it clearly isn't
         // redundant. It is explicitly needed for Java serialization to be able to create instances via reflection.
         @SuppressWarnings("checkstyle:RedundantModifier")
-        public Proxy() {
+        public Proxy2() {
         }
 
-        Proxy(AppendEntriesReply appendEntriesReply) {
+        Proxy2(final AppendEntriesReply appendEntriesReply) {
             this.appendEntriesReply = appendEntriesReply;
         }
 
         @Override
-        public void writeExternal(ObjectOutput out) throws IOException {
+        public void writeExternal(final ObjectOutput out) throws IOException {
             out.writeShort(appendEntriesReply.raftVersion);
             out.writeLong(appendEntriesReply.getTerm());
             out.writeObject(appendEntriesReply.followerId);
@@ -130,10 +150,11 @@ public class AppendEntriesReply extends AbstractRaftRPC {
             out.writeLong(appendEntriesReply.logLastTerm);
             out.writeShort(appendEntriesReply.payloadVersion);
             out.writeBoolean(appendEntriesReply.forceInstallSnapshot);
+            out.writeBoolean(appendEntriesReply.needsLeaderAddress);
         }
 
         @Override
-        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
             short raftVersion = in.readShort();
             long term = in.readLong();
             String followerId = (String) in.readObject();
@@ -142,11 +163,14 @@ public class AppendEntriesReply extends AbstractRaftRPC {
             long logLastTerm = in.readLong();
             short payloadVersion = in.readShort();
             boolean forceInstallSnapshot = in.readBoolean();
+            boolean needsLeaderAddress = in.readBoolean();
 
             appendEntriesReply = new AppendEntriesReply(followerId, term, success, logLastIndex, logLastTerm,
-                    payloadVersion, forceInstallSnapshot, raftVersion);
+                    payloadVersion, forceInstallSnapshot, needsLeaderAddress, raftVersion,
+                    RaftVersions.CURRENT_VERSION);
         }
 
+        @java.io.Serial
         private Object readResolve() {
             return appendEntriesReply;
         }