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;
10 import java.util.ArrayList;
11 import java.util.List;
14 * Abstract class handling the mapping of
15 * logical LogEntry Index and the physical list index.
17 public abstract class AbstractReplicatedLogImpl implements ReplicatedLog {
19 // We define this as ArrayList so we can use ensureCapacity.
20 protected ArrayList<ReplicatedLogEntry> journal;
22 protected long snapshotIndex = -1;
23 protected long snapshotTerm = -1;
25 // to be used for rollback during save snapshot failure
26 protected ArrayList<ReplicatedLogEntry> snapshottedJournal;
27 protected long previousSnapshotIndex = -1;
28 protected long previousSnapshotTerm = -1;
29 protected int dataSize = 0;
31 public AbstractReplicatedLogImpl(long snapshotIndex,
32 long snapshotTerm, List<ReplicatedLogEntry> unAppliedEntries) {
33 this.snapshotIndex = snapshotIndex;
34 this.snapshotTerm = snapshotTerm;
35 this.journal = new ArrayList<>(unAppliedEntries);
38 public AbstractReplicatedLogImpl() {
39 this.journal = new ArrayList<>();
42 protected int adjustedIndex(long logEntryIndex) {
43 if(snapshotIndex < 0){
44 return (int) logEntryIndex;
46 return (int) (logEntryIndex - (snapshotIndex + 1));
50 public ReplicatedLogEntry get(long logEntryIndex) {
51 int adjustedIndex = adjustedIndex(logEntryIndex);
53 if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
54 // physical index should be less than list size and >= 0
58 return journal.get(adjustedIndex);
62 public ReplicatedLogEntry last() {
63 if (journal.isEmpty()) {
66 // get the last entry directly from the physical index
67 return journal.get(journal.size() - 1);
71 public long lastIndex() {
72 if (journal.isEmpty()) {
73 // it can happen that after snapshot, all the entries of the
74 // journal are trimmed till lastApplied, so lastIndex = snapshotIndex
77 return last().getIndex();
81 public long lastTerm() {
82 if (journal.isEmpty()) {
83 // it can happen that after snapshot, all the entries of the
84 // journal are trimmed till lastApplied, so lastTerm = snapshotTerm
87 return last().getTerm();
91 public void removeFrom(long logEntryIndex) {
92 int adjustedIndex = adjustedIndex(logEntryIndex);
93 if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
94 // physical index should be less than list size and >= 0
97 journal.subList(adjustedIndex , journal.size()).clear();
101 public void append(ReplicatedLogEntry replicatedLogEntry) {
102 journal.add(replicatedLogEntry);
106 public void increaseJournalLogCapacity(int amount) {
107 journal.ensureCapacity(journal.size() + amount);
111 public List<ReplicatedLogEntry> getFrom(long logEntryIndex) {
112 return getFrom(logEntryIndex, journal.size());
116 public List<ReplicatedLogEntry> getFrom(long logEntryIndex, int max) {
117 int adjustedIndex = adjustedIndex(logEntryIndex);
118 int size = journal.size();
119 List<ReplicatedLogEntry> entries = new ArrayList<>(100);
120 if (adjustedIndex >= 0 && adjustedIndex < size) {
121 // physical index should be less than list size and >= 0
122 int maxIndex = adjustedIndex + max;
126 entries.addAll(journal.subList(adjustedIndex, maxIndex));
134 return journal.size();
138 public boolean isPresent(long logEntryIndex) {
139 if (logEntryIndex > lastIndex()) {
140 // if the request logical index is less than the last present in the list
143 int adjustedIndex = adjustedIndex(logEntryIndex);
144 return (adjustedIndex >= 0);
148 public boolean isInSnapshot(long logEntryIndex) {
149 return logEntryIndex <= snapshotIndex && snapshotIndex != -1;
153 public long getSnapshotIndex() {
154 return snapshotIndex;
158 public long getSnapshotTerm() {
163 public abstract void appendAndPersist(ReplicatedLogEntry replicatedLogEntry);
166 public abstract void removeFromAndPersist(long index);
169 public void setSnapshotIndex(long snapshotIndex) {
170 this.snapshotIndex = snapshotIndex;
174 public void setSnapshotTerm(long snapshotTerm) {
175 this.snapshotTerm = snapshotTerm;
179 public void clear(int startIndex, int endIndex) {
180 journal.subList(startIndex, endIndex).clear();
184 public void snapshotPreCommit(long snapshotCapturedIndex, long snapshotCapturedTerm) {
185 snapshottedJournal = new ArrayList<>(journal.size());
187 snapshottedJournal.addAll(journal.subList(0, (int)(snapshotCapturedIndex - snapshotIndex)));
188 clear(0, (int) (snapshotCapturedIndex - snapshotIndex));
190 previousSnapshotIndex = snapshotIndex;
191 setSnapshotIndex(snapshotCapturedIndex);
193 previousSnapshotTerm = snapshotTerm;
194 setSnapshotTerm(snapshotCapturedTerm);
198 public void snapshotCommit() {
199 snapshottedJournal = null;
200 previousSnapshotIndex = -1;
201 previousSnapshotTerm = -1;
206 public void snapshotRollback() {
207 snapshottedJournal.addAll(journal);
208 journal = snapshottedJournal;
209 snapshottedJournal = null;
211 snapshotIndex = previousSnapshotIndex;
212 previousSnapshotIndex = -1;
214 snapshotTerm = previousSnapshotTerm;
215 previousSnapshotTerm = -1;