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.persisted;
10 import com.google.common.collect.ImmutableList;
11 import java.io.Externalizable;
12 import java.io.IOException;
13 import java.io.ObjectInput;
14 import java.io.ObjectOutput;
15 import java.io.Serializable;
16 import java.util.List;
17 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
18 import org.opendaylight.controller.cluster.raft.messages.Payload;
21 * Represents a snapshot of the raft data.
23 * @author Thomas Pantelis
25 public sealed class Snapshot implements Serializable {
27 * Implementations of this interface are used as the state payload for a snapshot.
29 * @author Thomas Pantelis
31 public interface State extends Serializable {
33 * Indicate whether the snapshot requires migration, i.e. a new snapshot should be created after recovery.
34 * Default implementation returns false, i.e. do not re-snapshot.
36 * @return True if complete recovery based upon this snapshot should trigger a new snapshot.
38 default boolean needsMigration() {
43 @Deprecated(since = "7.0.0", forRemoval = true)
44 private static final class Legacy extends Snapshot implements LegacySerializable {
46 private static final long serialVersionUID = 1L;
48 Legacy(final State state, final List<ReplicatedLogEntry> unAppliedEntries, final long lastIndex,
49 final long lastTerm, final long lastAppliedIndex, final long lastAppliedTerm, final long electionTerm,
50 final String electionVotedFor, final ServerConfigurationPayload serverConfig) {
51 super(state, unAppliedEntries, lastIndex, lastTerm, lastAppliedIndex, lastAppliedTerm, electionTerm,
52 electionVotedFor, serverConfig);
56 @Deprecated(since = "7.0.0", forRemoval = true)
57 private static final class Proxy implements Externalizable {
59 private static final long serialVersionUID = 1L;
61 private Snapshot snapshot = null;
63 // checkstyle flags the public modifier as redundant which really doesn't make sense since it clearly isn't
64 // redundant. It is explicitly needed for Java serialization to be able to create instances via reflection.
65 @SuppressWarnings("checkstyle:RedundantModifier")
71 public void writeExternal(final ObjectOutput out) throws IOException {
72 out.writeLong(snapshot.lastIndex);
73 out.writeLong(snapshot.lastTerm);
74 out.writeLong(snapshot.lastAppliedIndex);
75 out.writeLong(snapshot.lastAppliedTerm);
76 out.writeLong(snapshot.electionTerm);
77 out.writeObject(snapshot.electionVotedFor);
78 out.writeObject(snapshot.serverConfig);
80 out.writeInt(snapshot.unAppliedEntries.size());
81 for (ReplicatedLogEntry e: snapshot.unAppliedEntries) {
82 out.writeLong(e.getIndex());
83 out.writeLong(e.getTerm());
84 out.writeObject(e.getData());
87 out.writeObject(snapshot.state);
91 public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
92 long lastIndex = in.readLong();
93 long lastTerm = in.readLong();
94 long lastAppliedIndex = in.readLong();
95 long lastAppliedTerm = in.readLong();
96 long electionTerm = in.readLong();
97 String electionVotedFor = (String) in.readObject();
98 ServerConfigurationPayload serverConfig = (ServerConfigurationPayload) in.readObject();
100 int size = in.readInt();
101 var unAppliedEntries = ImmutableList.<ReplicatedLogEntry>builderWithExpectedSize(size);
102 for (int i = 0; i < size; i++) {
103 unAppliedEntries.add(new SimpleReplicatedLogEntry(in.readLong(), in.readLong(),
104 (Payload) in.readObject()));
107 State state = (State) in.readObject();
109 snapshot = new Legacy(state, unAppliedEntries.build(), lastIndex, lastTerm, lastAppliedIndex,
110 lastAppliedTerm, electionTerm, electionVotedFor, serverConfig);
114 private Object readResolve() {
120 private static final long serialVersionUID = 1L;
122 private final State state;
123 private final List<ReplicatedLogEntry> unAppliedEntries;
124 private final long lastIndex;
125 private final long lastTerm;
126 private final long lastAppliedIndex;
127 private final long lastAppliedTerm;
128 private final long electionTerm;
129 private final String electionVotedFor;
130 private final ServerConfigurationPayload serverConfig;
132 Snapshot(final State state, final List<ReplicatedLogEntry> unAppliedEntries, final long lastIndex,
133 final long lastTerm, final long lastAppliedIndex, final long lastAppliedTerm, final long electionTerm,
134 final String electionVotedFor, final ServerConfigurationPayload serverConfig) {
136 this.unAppliedEntries = unAppliedEntries;
137 this.lastIndex = lastIndex;
138 this.lastTerm = lastTerm;
139 this.lastAppliedIndex = lastAppliedIndex;
140 this.lastAppliedTerm = lastAppliedTerm;
141 this.electionTerm = electionTerm;
142 this.electionVotedFor = electionVotedFor;
143 this.serverConfig = serverConfig;
146 public static Snapshot create(final State state, final List<ReplicatedLogEntry> entries, final long lastIndex,
147 final long lastTerm, final long lastAppliedIndex, final long lastAppliedTerm, final long electionTerm,
148 final String electionVotedFor, final ServerConfigurationPayload serverConfig) {
149 return new Snapshot(state, entries, lastIndex, lastTerm, lastAppliedIndex, lastAppliedTerm,
150 electionTerm, electionVotedFor, serverConfig);
153 public State getState() {
157 public List<ReplicatedLogEntry> getUnAppliedEntries() {
158 return unAppliedEntries;
161 public long getLastTerm() {
165 public long getLastAppliedIndex() {
166 return lastAppliedIndex;
169 public long getLastAppliedTerm() {
170 return lastAppliedTerm;
173 public long getLastIndex() {
177 public long getElectionTerm() {
181 public String getElectionVotedFor() {
182 return electionVotedFor;
185 public ServerConfigurationPayload getServerConfiguration() {
190 public final Object writeReplace() {
195 public final String toString() {
196 return "Snapshot [lastIndex=" + lastIndex + ", lastTerm=" + lastTerm + ", lastAppliedIndex=" + lastAppliedIndex
197 + ", lastAppliedTerm=" + lastAppliedTerm + ", unAppliedEntries size=" + unAppliedEntries.size()
198 + ", state=" + state + ", electionTerm=" + electionTerm + ", electionVotedFor="
199 + electionVotedFor + ", ServerConfigPayload=" + serverConfig + "]";