2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.cluster.raft.messages;
10 import com.google.common.annotations.VisibleForTesting;
11 import java.io.Externalizable;
12 import java.io.IOException;
13 import java.io.ObjectInput;
14 import java.io.ObjectOutput;
15 import org.opendaylight.controller.cluster.raft.RaftVersions;
18 * Reply for the AppendEntries message.
20 public final class AppendEntriesReply extends AbstractRaftRPC {
22 private static final long serialVersionUID = -7487547356392536683L;
24 // true if follower contained entry matching
25 // prevLogIndex and prevLogTerm
26 private final boolean success;
28 // The index of the last entry in the followers log
29 // This will be used to set the matchIndex for the follower on the
31 private final long logLastIndex;
33 private final long logLastTerm;
35 // The followerId - this will be used to figure out which follower is
37 private final String followerId;
39 private final short payloadVersion;
41 private final short raftVersion;
43 private final boolean forceInstallSnapshot;
45 private final boolean needsLeaderAddress;
47 private final short recipientRaftVersion;
50 public AppendEntriesReply(final String followerId, final long term, final boolean success, final long logLastIndex,
51 final long logLastTerm, final short payloadVersion) {
52 this(followerId, term, success, logLastIndex, logLastTerm, payloadVersion, false, false,
53 RaftVersions.CURRENT_VERSION);
56 public AppendEntriesReply(final String followerId, final long term, final boolean success, final long logLastIndex,
57 final long logLastTerm, final short payloadVersion, final boolean forceInstallSnapshot,
58 final boolean needsLeaderAddress, final short recipientRaftVersion) {
59 this(followerId, term, success, logLastIndex, logLastTerm, payloadVersion, forceInstallSnapshot,
60 needsLeaderAddress, RaftVersions.CURRENT_VERSION, recipientRaftVersion);
63 AppendEntriesReply(final String followerId, final long term, final boolean success, final long logLastIndex,
64 final long logLastTerm, final short payloadVersion, final boolean forceInstallSnapshot,
65 final boolean needsLeaderAddress, final short raftVersion, final short recipientRaftVersion) {
67 this.followerId = followerId;
68 this.success = success;
69 this.logLastIndex = logLastIndex;
70 this.logLastTerm = logLastTerm;
71 this.payloadVersion = payloadVersion;
72 this.forceInstallSnapshot = forceInstallSnapshot;
73 this.raftVersion = raftVersion;
74 this.needsLeaderAddress = needsLeaderAddress;
75 this.recipientRaftVersion = recipientRaftVersion;
78 public boolean isSuccess() {
82 public long getLogLastIndex() {
86 public long getLogLastTerm() {
90 public String getFollowerId() {
94 public short getPayloadVersion() {
95 return payloadVersion;
98 public short getRaftVersion() {
102 public boolean isForceInstallSnapshot() {
103 return forceInstallSnapshot;
106 public boolean isNeedsLeaderAddress() {
107 return needsLeaderAddress;
111 public String toString() {
112 return "AppendEntriesReply [term=" + getTerm() + ", success=" + success + ", followerId=" + followerId
113 + ", logLastIndex=" + logLastIndex + ", logLastTerm=" + logLastTerm + ", forceInstallSnapshot="
114 + forceInstallSnapshot + ", needsLeaderAddress=" + needsLeaderAddress
115 + ", payloadVersion=" + payloadVersion + ", raftVersion=" + raftVersion
116 + ", recipientRaftVersion=" + recipientRaftVersion + "]";
120 Object writeReplace() {
121 return recipientRaftVersion <= RaftVersions.FLUORINE_VERSION ? new Proxy2(this) : new AR(this);
125 * Fluorine version that adds the needsLeaderAddress flag.
127 private static class Proxy2 implements Externalizable {
129 private static final long serialVersionUID = 1L;
131 private AppendEntriesReply appendEntriesReply;
133 // checkstyle flags the public modifier as redundant which really doesn't make sense since it clearly isn't
134 // redundant. It is explicitly needed for Java serialization to be able to create instances via reflection.
135 @SuppressWarnings("checkstyle:RedundantModifier")
139 Proxy2(final AppendEntriesReply appendEntriesReply) {
140 this.appendEntriesReply = appendEntriesReply;
144 public void writeExternal(final ObjectOutput out) throws IOException {
145 out.writeShort(appendEntriesReply.raftVersion);
146 out.writeLong(appendEntriesReply.getTerm());
147 out.writeObject(appendEntriesReply.followerId);
148 out.writeBoolean(appendEntriesReply.success);
149 out.writeLong(appendEntriesReply.logLastIndex);
150 out.writeLong(appendEntriesReply.logLastTerm);
151 out.writeShort(appendEntriesReply.payloadVersion);
152 out.writeBoolean(appendEntriesReply.forceInstallSnapshot);
153 out.writeBoolean(appendEntriesReply.needsLeaderAddress);
157 public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
158 short raftVersion = in.readShort();
159 long term = in.readLong();
160 String followerId = (String) in.readObject();
161 boolean success = in.readBoolean();
162 long logLastIndex = in.readLong();
163 long logLastTerm = in.readLong();
164 short payloadVersion = in.readShort();
165 boolean forceInstallSnapshot = in.readBoolean();
166 boolean needsLeaderAddress = in.readBoolean();
168 appendEntriesReply = new AppendEntriesReply(followerId, term, success, logLastIndex, logLastTerm,
169 payloadVersion, forceInstallSnapshot, needsLeaderAddress, raftVersion,
170 RaftVersions.CURRENT_VERSION);
174 private Object readResolve() {
175 return appendEntriesReply;