Improve segmented journal actor metrics
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / main / java / org / opendaylight / controller / cluster / raft / messages / AppendEntriesReply.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.cluster.raft.messages;
9
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;
16
17 /**
18  * Reply for the AppendEntries message.
19  */
20 public final class AppendEntriesReply extends AbstractRaftRPC {
21     @java.io.Serial
22     private static final long serialVersionUID = -7487547356392536683L;
23
24     // true if follower contained entry matching
25     // prevLogIndex and prevLogTerm
26     private final boolean success;
27
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
30     // Leader
31     private final long logLastIndex;
32
33     private final long logLastTerm;
34
35     // The followerId - this will be used to figure out which follower is
36     // responding
37     private final String followerId;
38
39     private final short payloadVersion;
40
41     private final short raftVersion;
42
43     private final boolean forceInstallSnapshot;
44
45     private final boolean needsLeaderAddress;
46
47     private final short recipientRaftVersion;
48
49     @VisibleForTesting
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);
54     }
55
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);
61     }
62
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) {
66         super(term);
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;
76     }
77
78     public boolean isSuccess() {
79         return success;
80     }
81
82     public long getLogLastIndex() {
83         return logLastIndex;
84     }
85
86     public long getLogLastTerm() {
87         return logLastTerm;
88     }
89
90     public String getFollowerId() {
91         return followerId;
92     }
93
94     public short getPayloadVersion() {
95         return payloadVersion;
96     }
97
98     public short getRaftVersion() {
99         return raftVersion;
100     }
101
102     public boolean isForceInstallSnapshot() {
103         return forceInstallSnapshot;
104     }
105
106     public boolean isNeedsLeaderAddress() {
107         return needsLeaderAddress;
108     }
109
110     @Override
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 + "]";
117     }
118
119     @Override
120     Object writeReplace() {
121         return recipientRaftVersion <= RaftVersions.FLUORINE_VERSION ? new Proxy2(this) : new AR(this);
122     }
123
124     /**
125      * Fluorine version that adds the needsLeaderAddress flag.
126      */
127     private static class Proxy2 implements Externalizable {
128         @java.io.Serial
129         private static final long serialVersionUID = 1L;
130
131         private AppendEntriesReply appendEntriesReply;
132
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")
136         public Proxy2() {
137         }
138
139         Proxy2(final AppendEntriesReply appendEntriesReply) {
140             this.appendEntriesReply = appendEntriesReply;
141         }
142
143         @Override
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);
154         }
155
156         @Override
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();
167
168             appendEntriesReply = new AppendEntriesReply(followerId, term, success, logLastIndex, logLastTerm,
169                     payloadVersion, forceInstallSnapshot, needsLeaderAddress, raftVersion,
170                     RaftVersions.CURRENT_VERSION);
171         }
172
173         @java.io.Serial
174         private Object readResolve() {
175             return appendEntriesReply;
176         }
177     }
178 }