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