Bug 5504: Add PreLeader raft state
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / MockRaftActorContext.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;
10
11 import akka.actor.ActorRef;
12 import akka.actor.ActorSelection;
13 import akka.actor.ActorSystem;
14 import akka.actor.Props;
15 import akka.japi.Procedure;
16 import java.io.Serializable;
17 import java.util.HashMap;
18 import java.util.Map;
19 import org.opendaylight.controller.cluster.NonPersistentDataProvider;
20 import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
21 import org.opendaylight.controller.cluster.raft.policy.RaftPolicy;
22 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 public class MockRaftActorContext extends RaftActorContextImpl {
27     private static final Logger LOG = LoggerFactory.getLogger(MockRaftActorContext.class);
28
29     private ActorSystem system;
30     private RaftPolicy raftPolicy;
31
32     private static ElectionTerm newElectionTerm() {
33         return new ElectionTerm() {
34             private long currentTerm = 1;
35             private String votedFor = "";
36
37             @Override
38             public long getCurrentTerm() {
39                 return currentTerm;
40             }
41
42             @Override
43             public String getVotedFor() {
44                 return votedFor;
45             }
46
47             @Override
48             public void update(long currentTerm, String votedFor){
49                 this.currentTerm = currentTerm;
50                 this.votedFor = votedFor;
51
52                 // TODO : Write to some persistent state
53             }
54
55             @Override public void updateAndPersist(long currentTerm,
56                 String votedFor) {
57                 update(currentTerm, votedFor);
58             }
59         };
60     }
61
62     public MockRaftActorContext(){
63         super(null, null, "test", newElectionTerm(), -1, -1, new HashMap<String, String>(),
64                 new DefaultConfigParamsImpl(), new NonPersistentDataProvider(), LOG);
65         setReplicatedLog(new MockReplicatedLogBuilder().build());
66     }
67
68     public MockRaftActorContext(String id, ActorSystem system, ActorRef actor){
69         super(actor, null, id, newElectionTerm(), -1, -1, new HashMap<String, String>(),
70                 new DefaultConfigParamsImpl(), new NonPersistentDataProvider(), LOG);
71
72         this.system = system;
73
74         initReplicatedLog();
75     }
76
77
78     public void initReplicatedLog(){
79         SimpleReplicatedLog replicatedLog = new SimpleReplicatedLog();
80         long term = getTermInformation().getCurrentTerm();
81         replicatedLog.append(new MockReplicatedLogEntry(term, 0, new MockPayload("1")));
82         replicatedLog.append(new MockReplicatedLogEntry(term, 1, new MockPayload("2")));
83         setReplicatedLog(replicatedLog);
84         setCommitIndex(replicatedLog.lastIndex());
85     }
86
87     @Override public ActorRef actorOf(Props props) {
88         return system.actorOf(props);
89     }
90
91     @Override public ActorSelection actorSelection(String path) {
92         return system.actorSelection(path);
93     }
94
95     @Override public ActorSystem getActorSystem() {
96         return this.system;
97     }
98
99     @Override public ActorSelection getPeerActorSelection(String peerId) {
100         String peerAddress = getPeerAddress(peerId);
101         if(peerAddress != null){
102             return actorSelection(peerAddress);
103         }
104         return null;
105     }
106
107     public void setPeerAddresses(Map<String, String> peerAddresses) {
108         for(String id: getPeerIds()) {
109             removePeer(id);
110         }
111
112         for(Map.Entry<String, String> e: peerAddresses.entrySet()) {
113             addToPeers(e.getKey(), e.getValue(), VotingState.VOTING);
114         }
115     }
116
117     @Override
118     public SnapshotManager getSnapshotManager() {
119         SnapshotManager snapshotManager = super.getSnapshotManager();
120         snapshotManager.setCreateSnapshotRunnable(() -> { });
121         return snapshotManager;
122     }
123
124     @Override
125     public RaftPolicy getRaftPolicy() {
126         return raftPolicy != null ? raftPolicy : super.getRaftPolicy();
127     }
128
129     public void setRaftPolicy(RaftPolicy raftPolicy) {
130         this.raftPolicy = raftPolicy;
131     }
132
133     public static class SimpleReplicatedLog extends AbstractReplicatedLogImpl {
134         @Override
135         public void appendAndPersist(
136             ReplicatedLogEntry replicatedLogEntry) {
137             append(replicatedLogEntry);
138         }
139
140         @Override
141         public int dataSize() {
142             return -1;
143         }
144
145         @Override
146         public void captureSnapshotIfReady(ReplicatedLogEntry replicatedLogEntry) {
147         }
148
149         @Override
150         public boolean removeFromAndPersist(long index) {
151             return removeFrom(index) >= 0;
152         }
153
154         @Override
155         public void appendAndPersist(ReplicatedLogEntry replicatedLogEntry, Procedure<ReplicatedLogEntry> callback) {
156             append(replicatedLogEntry);
157
158             if(callback != null) {
159                 try {
160                     callback.apply(replicatedLogEntry);
161                 } catch (Exception e) {
162                     e.printStackTrace();
163                 }
164             }
165         }
166     }
167
168     public static class MockPayload extends Payload implements Serializable {
169         private static final long serialVersionUID = 3121380393130864247L;
170         private String value = "";
171         private int size;
172
173         public MockPayload() {
174         }
175
176         public MockPayload(String s) {
177             this.value = s;
178             size = value.length();
179         }
180
181         public MockPayload(String s, int size) {
182             this(s);
183             this.size = size;
184         }
185
186         @Override
187         public int size() {
188             return size;
189         }
190
191         @Override
192         public String toString() {
193             return value;
194         }
195
196         @Override
197         public int hashCode() {
198             final int prime = 31;
199             int result = 1;
200             result = prime * result + ((value == null) ? 0 : value.hashCode());
201             return result;
202         }
203
204         @Override
205         public boolean equals(Object obj) {
206             if (this == obj) {
207                 return true;
208             }
209             if (obj == null) {
210                 return false;
211             }
212             if (getClass() != obj.getClass()) {
213                 return false;
214             }
215             MockPayload other = (MockPayload) obj;
216             if (value == null) {
217                 if (other.value != null) {
218                     return false;
219                 }
220             } else if (!value.equals(other.value)) {
221                 return false;
222             }
223             return true;
224         }
225     }
226
227     public static class MockReplicatedLogEntry implements ReplicatedLogEntry, Serializable {
228         private static final long serialVersionUID = 1L;
229
230         private final long term;
231         private final long index;
232         private final Payload data;
233
234         public MockReplicatedLogEntry(long term, long index, Payload data){
235
236             this.term = term;
237             this.index = index;
238             this.data = data;
239         }
240
241         @Override public Payload getData() {
242             return data;
243         }
244
245         @Override public long getTerm() {
246             return term;
247         }
248
249         @Override public long getIndex() {
250             return index;
251         }
252
253         @Override
254         public int size() {
255             return getData().size();
256         }
257
258         @Override
259         public int hashCode() {
260             final int prime = 31;
261             int result = 1;
262             result = prime * result + ((data == null) ? 0 : data.hashCode());
263             result = prime * result + (int) (index ^ (index >>> 32));
264             result = prime * result + (int) (term ^ (term >>> 32));
265             return result;
266         }
267
268         @Override
269         public boolean equals(Object obj) {
270             if (this == obj) {
271                 return true;
272             }
273             if (obj == null) {
274                 return false;
275             }
276             if (getClass() != obj.getClass()) {
277                 return false;
278             }
279             MockReplicatedLogEntry other = (MockReplicatedLogEntry) obj;
280             if (data == null) {
281                 if (other.data != null) {
282                     return false;
283                 }
284             } else if (!data.equals(other.data)) {
285                 return false;
286             }
287             if (index != other.index) {
288                 return false;
289             }
290             if (term != other.term) {
291                 return false;
292             }
293             return true;
294         }
295
296         @Override
297         public String toString() {
298             StringBuilder builder = new StringBuilder();
299             builder.append("MockReplicatedLogEntry [term=").append(term).append(", index=").append(index)
300                     .append(", data=").append(data).append("]");
301             return builder.toString();
302         }
303     }
304
305     public static class MockReplicatedLogBuilder {
306         private final ReplicatedLog mockLog = new SimpleReplicatedLog();
307
308         public  MockReplicatedLogBuilder createEntries(int start, int end, int term) {
309             for (int i=start; i<end; i++) {
310                 this.mockLog.append(new ReplicatedLogImplEntry(i, term, new MockRaftActorContext.MockPayload(Integer.toString(i))));
311             }
312             return this;
313         }
314
315         public  MockReplicatedLogBuilder addEntry(int index, int term, MockPayload payload) {
316             this.mockLog.append(new ReplicatedLogImplEntry(index, term, payload));
317             return this;
318         }
319
320         public ReplicatedLog build() {
321             return this.mockLog;
322         }
323     }
324
325     @Override
326     public void setCurrentBehavior(final RaftActorBehavior behavior) {
327         super.setCurrentBehavior(behavior);
328     }
329 }