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