Bug 7521: Convert Snapshot to store a State instance
[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.common.base.Throwables;
17 import com.google.common.io.ByteSource;
18 import java.io.IOException;
19 import java.io.OutputStream;
20 import java.io.Serializable;
21 import java.util.HashMap;
22 import java.util.Map;
23 import org.opendaylight.controller.cluster.NonPersistentDataProvider;
24 import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
25 import org.opendaylight.controller.cluster.raft.persisted.ByteState;
26 import org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry;
27 import org.opendaylight.controller.cluster.raft.persisted.Snapshot.State;
28 import org.opendaylight.controller.cluster.raft.policy.RaftPolicy;
29 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 public class MockRaftActorContext extends RaftActorContextImpl {
34     private static final Logger LOG = LoggerFactory.getLogger(MockRaftActorContext.class);
35
36     private ActorSystem system;
37     private RaftPolicy raftPolicy;
38
39     private static ElectionTerm newElectionTerm() {
40         return new ElectionTerm() {
41             private long currentTerm = 1;
42             private String votedFor = "";
43
44             @Override
45             public long getCurrentTerm() {
46                 return currentTerm;
47             }
48
49             @Override
50             public String getVotedFor() {
51                 return votedFor;
52             }
53
54             @Override
55             public void update(long newTerm, String newVotedFor) {
56                 this.currentTerm = newTerm;
57                 this.votedFor = newVotedFor;
58
59                 // TODO : Write to some persistent state
60             }
61
62             @Override public void updateAndPersist(long newTerm, String newVotedFor) {
63                 update(newTerm, newVotedFor);
64             }
65         };
66     }
67
68     public MockRaftActorContext() {
69         super(null, null, "test", newElectionTerm(), -1, -1, new HashMap<>(),
70                 new DefaultConfigParamsImpl(), new NonPersistentDataProvider(), applyState -> { }, LOG);
71         setReplicatedLog(new MockReplicatedLogBuilder().build());
72     }
73
74     public MockRaftActorContext(String id, ActorSystem system, ActorRef actor) {
75         super(actor, null, id, newElectionTerm(), -1, -1, new HashMap<>(),
76             new DefaultConfigParamsImpl(), new NonPersistentDataProvider(),
77             applyState -> actor.tell(applyState, actor), LOG);
78
79         this.system = system;
80
81         initReplicatedLog();
82     }
83
84
85     public void initReplicatedLog() {
86         SimpleReplicatedLog replicatedLog = new SimpleReplicatedLog();
87         long term = getTermInformation().getCurrentTerm();
88         replicatedLog.append(new SimpleReplicatedLogEntry(0, term, new MockPayload("1")));
89         replicatedLog.append(new SimpleReplicatedLogEntry(1, term, new MockPayload("2")));
90         setReplicatedLog(replicatedLog);
91         setCommitIndex(replicatedLog.lastIndex());
92         setLastApplied(replicatedLog.lastIndex());
93     }
94
95     @Override public ActorRef actorOf(Props props) {
96         return system.actorOf(props);
97     }
98
99     @Override public ActorSelection actorSelection(String path) {
100         return system.actorSelection(path);
101     }
102
103     @Override public ActorSystem getActorSystem() {
104         return this.system;
105     }
106
107     @Override public ActorSelection getPeerActorSelection(String peerId) {
108         String peerAddress = getPeerAddress(peerId);
109         if (peerAddress != null) {
110             return actorSelection(peerAddress);
111         }
112         return null;
113     }
114
115     public void setPeerAddresses(Map<String, String> peerAddresses) {
116         for (String id: getPeerIds()) {
117             removePeer(id);
118         }
119
120         for (Map.Entry<String, String> e: peerAddresses.entrySet()) {
121             addToPeers(e.getKey(), e.getValue(), VotingState.VOTING);
122         }
123     }
124
125     @Override
126     public SnapshotManager getSnapshotManager() {
127         SnapshotManager snapshotManager = super.getSnapshotManager();
128         snapshotManager.setCreateSnapshotConsumer(out -> { });
129
130         snapshotManager.setSnapshotCohort(new RaftActorSnapshotCohort() {
131             @Override
132             public State deserializeSnapshot(ByteSource snapshotBytes) throws IOException {
133                 return ByteState.of(snapshotBytes.read());
134             }
135
136             @Override
137             public void createSnapshot(ActorRef actorRef, java.util.Optional<OutputStream> installSnapshotStream) {
138             }
139
140             @Override
141             public void applySnapshot(State snapshotState) {
142             }
143         });
144
145         return snapshotManager;
146     }
147
148     @Override
149     public RaftPolicy getRaftPolicy() {
150         return raftPolicy != null ? raftPolicy : super.getRaftPolicy();
151     }
152
153     public void setRaftPolicy(RaftPolicy raftPolicy) {
154         this.raftPolicy = raftPolicy;
155     }
156
157     public static class SimpleReplicatedLog extends AbstractReplicatedLogImpl {
158         @Override
159         public int dataSize() {
160             return -1;
161         }
162
163         @Override
164         public void captureSnapshotIfReady(ReplicatedLogEntry replicatedLogEntry) {
165         }
166
167         @Override
168         public boolean shouldCaptureSnapshot(long logIndex) {
169             return false;
170         }
171
172         @Override
173         public boolean removeFromAndPersist(long index) {
174             return removeFrom(index) >= 0;
175         }
176
177         @Override
178         @SuppressWarnings("checkstyle:IllegalCatch")
179         public boolean appendAndPersist(ReplicatedLogEntry replicatedLogEntry, Procedure<ReplicatedLogEntry> callback,
180                 boolean doAsync) {
181             append(replicatedLogEntry);
182
183             if (callback != null) {
184                 try {
185                     callback.apply(replicatedLogEntry);
186                 } catch (Exception e) {
187                     Throwables.propagate(e);
188                 }
189             }
190
191             return true;
192         }
193     }
194
195     public static class MockPayload extends Payload implements Serializable {
196         private static final long serialVersionUID = 3121380393130864247L;
197         private String value = "";
198         private int size;
199
200         public MockPayload() {
201         }
202
203         public MockPayload(String data) {
204             this.value = data;
205             size = value.length();
206         }
207
208         public MockPayload(String data, int size) {
209             this(data);
210             this.size = size;
211         }
212
213         @Override
214         public int size() {
215             return size;
216         }
217
218         @Override
219         public String toString() {
220             return value;
221         }
222
223         @Override
224         public int hashCode() {
225             final int prime = 31;
226             int result = 1;
227             result = prime * result + (value == null ? 0 : value.hashCode());
228             return result;
229         }
230
231         @Override
232         public boolean equals(Object obj) {
233             if (this == obj) {
234                 return true;
235             }
236             if (obj == null) {
237                 return false;
238             }
239             if (getClass() != obj.getClass()) {
240                 return false;
241             }
242             MockPayload other = (MockPayload) obj;
243             if (value == null) {
244                 if (other.value != null) {
245                     return false;
246                 }
247             } else if (!value.equals(other.value)) {
248                 return false;
249             }
250             return true;
251         }
252     }
253
254     public static class MockReplicatedLogBuilder {
255         private final ReplicatedLog mockLog = new SimpleReplicatedLog();
256
257         public  MockReplicatedLogBuilder createEntries(int start, int end, int term) {
258             for (int i = start; i < end; i++) {
259                 this.mockLog.append(new SimpleReplicatedLogEntry(i, term,
260                         new MockRaftActorContext.MockPayload(Integer.toString(i))));
261             }
262             return this;
263         }
264
265         public  MockReplicatedLogBuilder addEntry(int index, int term, MockPayload payload) {
266             this.mockLog.append(new SimpleReplicatedLogEntry(index, term, payload));
267             return this;
268         }
269
270         public ReplicatedLog build() {
271             return this.mockLog;
272         }
273     }
274
275     @Override
276     public void setCurrentBehavior(final RaftActorBehavior behavior) {
277         super.setCurrentBehavior(behavior);
278     }
279 }