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