BUG 1623 - Clustering : Parsing Error thrown on startup
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / main / java / org / opendaylight / controller / cluster / raft / AbstractReplicatedLogImpl.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;
9
10 import java.util.ArrayList;
11 import java.util.List;
12
13 /**
14  * Abstract class handling the mapping of
15  * logical LogEntry Index and the physical list index.
16  */
17 public abstract class AbstractReplicatedLogImpl implements ReplicatedLog {
18
19     protected final List<ReplicatedLogEntry> journal;
20     protected final Object snapshot;
21     protected long snapshotIndex = -1;
22     protected long snapshotTerm = -1;
23
24     public AbstractReplicatedLogImpl(Object state, long snapshotIndex,
25         long snapshotTerm, List<ReplicatedLogEntry> unAppliedEntries) {
26         this.snapshot = state;
27         this.snapshotIndex = snapshotIndex;
28         this.snapshotTerm = snapshotTerm;
29         this.journal = new ArrayList<>(unAppliedEntries);
30     }
31
32
33     public AbstractReplicatedLogImpl() {
34         this.snapshot = null;
35         this.journal = new ArrayList<>();
36     }
37
38     protected int adjustedIndex(long logEntryIndex) {
39         if(snapshotIndex < 0){
40             return (int) logEntryIndex;
41         }
42         return (int) (logEntryIndex - (snapshotIndex + 1));
43     }
44
45     @Override
46     public ReplicatedLogEntry get(long logEntryIndex) {
47         int adjustedIndex = adjustedIndex(logEntryIndex);
48
49         if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
50             // physical index should be less than list size and >= 0
51             return null;
52         }
53
54         return journal.get(adjustedIndex);
55     }
56
57     @Override
58     public ReplicatedLogEntry last() {
59         if (journal.isEmpty()) {
60             return null;
61         }
62         // get the last entry directly from the physical index
63         return journal.get(journal.size() - 1);
64     }
65
66     @Override
67     public long lastIndex() {
68         if (journal.isEmpty()) {
69             // it can happen that after snapshot, all the entries of the
70             // journal are trimmed till lastApplied, so lastIndex = snapshotIndex
71             return snapshotIndex;
72         }
73         return last().getIndex();
74     }
75
76     @Override
77     public long lastTerm() {
78         if (journal.isEmpty()) {
79             // it can happen that after snapshot, all the entries of the
80             // journal are trimmed till lastApplied, so lastTerm = snapshotTerm
81             return snapshotTerm;
82         }
83         return last().getTerm();
84     }
85
86     @Override
87     public void removeFrom(long logEntryIndex) {
88         int adjustedIndex = adjustedIndex(logEntryIndex);
89         if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
90             // physical index should be less than list size and >= 0
91             return;
92         }
93         journal.subList(adjustedIndex , journal.size()).clear();
94     }
95
96     @Override
97     public void append(ReplicatedLogEntry replicatedLogEntry) {
98         journal.add(replicatedLogEntry);
99     }
100
101     @Override
102     public List<ReplicatedLogEntry> getFrom(long logEntryIndex) {
103         return getFrom(logEntryIndex, journal.size());
104     }
105
106     @Override
107     public List<ReplicatedLogEntry> getFrom(long logEntryIndex, int max) {
108         int adjustedIndex = adjustedIndex(logEntryIndex);
109         int size = journal.size();
110         List<ReplicatedLogEntry> entries = new ArrayList<>(100);
111         if (adjustedIndex >= 0 && adjustedIndex < size) {
112             // physical index should be less than list size and >= 0
113             int maxIndex = adjustedIndex + max;
114             if(maxIndex > size){
115                 maxIndex = size;
116             }
117             entries.addAll(journal.subList(adjustedIndex, maxIndex));
118         }
119         return entries;
120     }
121
122
123     @Override
124     public long size() {
125        return journal.size();
126     }
127
128     @Override
129     public boolean isPresent(long logEntryIndex) {
130         if (logEntryIndex > lastIndex()) {
131             // if the request logical index is less than the last present in the list
132             return false;
133         }
134         int adjustedIndex = adjustedIndex(logEntryIndex);
135         return (adjustedIndex >= 0);
136     }
137
138     @Override
139     public boolean isInSnapshot(long logEntryIndex) {
140         return logEntryIndex <= snapshotIndex;
141     }
142
143     @Override
144     public Object getSnapshot() {
145         return snapshot;
146     }
147
148     @Override
149     public long getSnapshotIndex() {
150         return snapshotIndex;
151     }
152
153     @Override
154     public long getSnapshotTerm() {
155         return snapshotTerm;
156     }
157
158     @Override
159     public abstract void appendAndPersist(ReplicatedLogEntry replicatedLogEntry);
160
161     @Override
162     public abstract void removeFromAndPersist(long index);
163 }