dc1ebf0730fd49bd7b3b73ba3c54e4c5127bc02c
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / main / java / org / opendaylight / controller / cluster / raft / messages / AppendEntries.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
9 package org.opendaylight.controller.cluster.raft.messages;
10
11 import java.io.Externalizable;
12 import java.io.IOException;
13 import java.io.ObjectInput;
14 import java.io.ObjectOutput;
15 import java.util.ArrayList;
16 import java.util.List;
17 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
18 import org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry;
19 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
20
21 /**
22  * Invoked by leader to replicate log entries (§5.3); also used as
23  * heartbeat (§5.2).
24  */
25 public class AppendEntries extends AbstractRaftRPC {
26     private static final long serialVersionUID = 1L;
27
28     // So that follower can redirect clients
29     private final String leaderId;
30
31     // Index of log entry immediately preceding new ones
32     private final long prevLogIndex;
33
34     // term of prevLogIndex entry
35     private final long prevLogTerm;
36
37     // log entries to store (empty for heartbeat;
38     // may send more than one for efficiency)
39     private transient List<ReplicatedLogEntry> entries;
40
41     // leader's commitIndex
42     private final long leaderCommit;
43
44     // index which has been replicated successfully to all followers, -1 if none
45     private final long replicatedToAllIndex;
46
47     private final short payloadVersion;
48
49     public AppendEntries(long term, String leaderId, long prevLogIndex, long prevLogTerm,
50             List<ReplicatedLogEntry> entries, long leaderCommit, long replicatedToAllIndex, short payloadVersion) {
51         super(term);
52         this.leaderId = leaderId;
53         this.prevLogIndex = prevLogIndex;
54         this.prevLogTerm = prevLogTerm;
55         this.entries = entries;
56         this.leaderCommit = leaderCommit;
57         this.replicatedToAllIndex = replicatedToAllIndex;
58         this.payloadVersion = payloadVersion;
59     }
60
61     public String getLeaderId() {
62         return leaderId;
63     }
64
65     public long getPrevLogIndex() {
66         return prevLogIndex;
67     }
68
69     public long getPrevLogTerm() {
70         return prevLogTerm;
71     }
72
73     public List<ReplicatedLogEntry> getEntries() {
74         return entries;
75     }
76
77     public long getLeaderCommit() {
78         return leaderCommit;
79     }
80
81     public long getReplicatedToAllIndex() {
82         return replicatedToAllIndex;
83     }
84
85     public short getPayloadVersion() {
86         return payloadVersion;
87     }
88
89     @Override
90     public String toString() {
91         StringBuilder builder = new StringBuilder();
92         builder.append("AppendEntries [leaderId=").append(leaderId).append(", prevLogIndex=").append(prevLogIndex)
93                 .append(", prevLogTerm=").append(prevLogTerm).append(", leaderCommit=").append(leaderCommit)
94                 .append(", replicatedToAllIndex=").append(replicatedToAllIndex).append(", payloadVersion=")
95                 .append(payloadVersion).append(", entries=").append(entries).append("]");
96         return builder.toString();
97     }
98
99     private Object writeReplace() {
100         return new Proxy(this);
101     }
102
103     private static class Proxy implements Externalizable {
104         private static final long serialVersionUID = 1L;
105
106         private AppendEntries appendEntries;
107
108         public Proxy() {
109         }
110
111         Proxy(AppendEntries appendEntries) {
112             this.appendEntries = appendEntries;
113         }
114
115         @Override
116         public void writeExternal(ObjectOutput out) throws IOException {
117             out.writeLong(appendEntries.getTerm());
118             out.writeObject(appendEntries.leaderId);
119             out.writeLong(appendEntries.prevLogTerm);
120             out.writeLong(appendEntries.prevLogIndex);
121             out.writeLong(appendEntries.leaderCommit);
122             out.writeLong(appendEntries.replicatedToAllIndex);
123             out.writeShort(appendEntries.payloadVersion);
124
125             out.writeInt(appendEntries.entries.size());
126             for(ReplicatedLogEntry e: appendEntries.entries) {
127                 out.writeLong(e.getIndex());
128                 out.writeLong(e.getTerm());
129                 out.writeObject(e.getData());
130             }
131         }
132
133         @Override
134         public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
135             long term = in.readLong();
136             String leaderId = (String) in.readObject();
137             long prevLogTerm = in.readLong();
138             long prevLogIndex = in.readLong();
139             long leaderCommit = in.readLong();
140             long replicatedToAllIndex = in.readLong();
141             short payloadVersion = in.readShort();
142
143             int size = in.readInt();
144             List<ReplicatedLogEntry> entries = new ArrayList<>(size);
145             for(int i = 0; i < size; i++) {
146                 entries.add(new ReplicatedLogImplEntry(in.readLong(), in.readLong(), (Payload) in.readObject()));
147             }
148
149             appendEntries = new AppendEntries(term, leaderId, prevLogIndex, prevLogTerm, entries, leaderCommit,
150                     replicatedToAllIndex, payloadVersion);
151         }
152
153         private Object readResolve() {
154             return appendEntries;
155         }
156     }
157 }