Bug-2277 : Isolated Leader Implementation
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / main / java / org / opendaylight / controller / cluster / example / TestDriver.java
1 package org.opendaylight.controller.cluster.example;
2
3 import akka.actor.ActorRef;
4 import akka.actor.ActorSystem;
5 import com.google.common.base.Optional;
6 import org.opendaylight.controller.cluster.example.messages.PrintRole;
7 import org.opendaylight.controller.cluster.example.messages.PrintState;
8 import org.opendaylight.controller.cluster.raft.ConfigParams;
9
10 import java.io.BufferedReader;
11 import java.io.InputStreamReader;
12 import java.util.HashMap;
13 import java.util.Map;
14 import java.util.concurrent.ConcurrentHashMap;
15
16 /**
17  * This is a test driver for testing akka-raft implementation
18  * Its uses ExampleActors and threads to push content(key-vals) to these actors
19  * Each ExampleActor can have one or more ClientActors. Each ClientActor spawns
20  * a thread and starts push logs to the actor its assigned to.
21  */
22 public class TestDriver {
23
24     private static final ActorSystem actorSystem = ActorSystem.create();
25     private static Map<String, String> allPeers = new HashMap<>();
26     private static Map<String, ActorRef> clientActorRefs  = new HashMap<String, ActorRef>();
27     private static Map<String, ActorRef> actorRefs = new HashMap<String, ActorRef>();
28     private static LogGenerator logGenerator = new LogGenerator();
29     private int nameCounter = 0;
30     private static ConfigParams configParams = new ExampleConfigParamsImpl();
31
32     /**
33      * Create nodes, add clients and start logging.
34      * Commands
35      *  bye
36      *  createNodes:{num}
37      *  stopNode:{nodeName}
38      *  reinstateNode:{nodeName}
39      *  addClients:{num}
40      *  addClientsToNode:{nodeName, num}
41      *  startLogging
42      *  stopLogging
43      *  startLoggingForClient:{nodeName}
44      *  stopLoggingForClient:{nodeName}
45      *  printNodes
46      *  printState
47      *
48      *  Note: when run on IDE and on debug log level, the debug logs in
49      *  AbstractUptypedActor and AbstractUptypedPersistentActor would need to be commented out.
50      *  Also RaftActor handleCommand(), debug log which prints for every command other than AE/AER
51      *
52      * @param args
53      * @throws Exception
54      */
55     public static void main(String[] args) throws Exception {
56         TestDriver td = new TestDriver();
57
58         System.out.println("Enter command (type bye to exit):");
59
60
61         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
62         while(true) {
63             String command = br.readLine();
64             if (command.startsWith("bye")) {
65                 System.exit(0);
66
67             } else if (command.startsWith("createNodes")) {
68                 String[] arr = command.split(":");
69                 int n = Integer.parseInt(arr[1]);
70                 td.createNodes(n);
71
72             } else if (command.startsWith("addClients")) {
73                 String[] arr = command.split(":");
74                 int n = Integer.parseInt(arr[1]);
75                 td.addClients(n);
76
77             } else if (command.startsWith("addClientsToNode")) {
78                 String[] arr = command.split(":");
79                 String nodeName = arr[1];
80                 int n = Integer.parseInt(arr[1]);
81                 td.addClientsToNode(nodeName, n);
82
83             } else if (command.startsWith("stopNode")) {
84                 String[] arr = command.split(":");
85                 td.stopNode(arr[1]);
86
87             } else if (command.startsWith("reinstateNode")) {
88                 String[] arr = command.split(":");
89                 td.reinstateNode(arr[1]);
90
91             } else if (command.startsWith("startLogging")) {
92                 td.startAllLogging();
93
94             } else if (command.startsWith("startLoggingForClient")) {
95                 String[] arr = command.split(":");
96                 td.startLoggingForClient(clientActorRefs.get(arr[1]));
97
98             } else if (command.startsWith("stopLogging")) {
99                 td.stopAllLogging();
100
101             } else if (command.startsWith("stopLoggingForClient")) {
102                 String[] arr = command.split(":");
103                 td.stopLoggingForClient(clientActorRefs.get(arr[1]));
104
105             } else if (command.startsWith("printState")) {
106                 td.printState();
107             } else if (command.startsWith("printNodes")) {
108                 td.printNodes();
109             } else {
110                 System.out.println("Invalid command:" + command);
111             }
112
113         }
114     }
115
116     public static ActorRef createExampleActor(String name) {
117         return actorSystem.actorOf(ExampleActor.props(name, withoutPeer(name),
118             Optional.of(configParams)), name);
119     }
120
121     public void createNodes(int num) {
122         for (int i=0; i < num; i++)  {
123             nameCounter = nameCounter + 1;
124             allPeers.put("example-"+nameCounter, "akka://default/user/example-"+nameCounter);
125         }
126
127         for (String s : allPeers.keySet())  {
128             ActorRef exampleActor = createExampleActor(s);
129             actorRefs.put(s, exampleActor);
130             System.out.println("Created node:"+s);
131
132         }
133     }
134
135     // add num clients to all nodes in the system
136     public void addClients(int num) {
137         for(Map.Entry<String,ActorRef> actorRefEntry : actorRefs.entrySet()) {
138             for (int i=0; i < num; i++) {
139                 String clientName = "client-" + i + "-" + actorRefEntry.getKey();
140                 ActorRef clientActor = actorSystem.actorOf(
141                     ClientActor.props(actorRefEntry.getValue()), clientName);
142                 clientActorRefs.put(clientName, clientActor);
143                 System.out.println("Created client-node:" + clientName);
144             }
145         }
146     }
147
148     // add num clients to a node
149     public void addClientsToNode(String actorName, int num) {
150         ActorRef actorRef = actorRefs.get(actorName);
151         for (int i=0; i < num; i++) {
152             String clientName = "client-" + i + "-" + actorName;
153             clientActorRefs.put(clientName,
154                 actorSystem.actorOf(ClientActor.props(actorRef), clientName));
155             System.out.println("Added client-node:" + clientName);
156         }
157     }
158
159     public void stopNode(String actorName) {
160         ActorRef actorRef = actorRefs.get(actorName);
161
162         for (Map.Entry<String,ActorRef> entry : clientActorRefs.entrySet()) {
163             if (entry.getKey().endsWith(actorName)) {
164                 actorSystem.stop(entry.getValue());
165             }
166         }
167
168         actorSystem.stop(actorRef);
169         actorRefs.remove(actorName);
170         allPeers.remove(actorName);
171     }
172
173     public void reinstateNode(String actorName) {
174         String address = "akka://default/user/"+actorName;
175         allPeers.put(actorName, address);
176
177         ActorRef exampleActor = createExampleActor(actorName);
178         actorRefs.put(actorName, exampleActor);
179
180         addClientsToNode(actorName, 1);
181     }
182
183     public void startAllLogging() {
184         if(!clientActorRefs.isEmpty()) {
185             for(Map.Entry<String,ActorRef> client : clientActorRefs.entrySet()) {
186                 logGenerator.startLoggingForClient(client.getValue());
187                 System.out.println("Started logging for client:"+client.getKey());
188             }
189         } else {
190             System.out.println("There are no clients for any nodes. First create clients using commands- addClients:<num> or addClientsToNode:<nodename>:<num>");
191         }
192
193     }
194
195     public void startLoggingForClient(ActorRef client) {
196         logGenerator.startLoggingForClient(client);
197     }
198
199     public void stopAllLogging() {
200         for(Map.Entry<String,ActorRef> client : clientActorRefs.entrySet()) {
201             logGenerator.stopLoggingForClient(client.getValue());
202         }
203     }
204
205     public void stopLoggingForClient(ActorRef client) {
206         logGenerator.stopLoggingForClient(client);
207     }
208
209     public void printState() {
210         for (ActorRef ref : actorRefs.values()) {
211             ref.tell(new PrintState(), null);
212         }
213     }
214
215     public void printNodes() {
216         for (ActorRef ref : actorRefs.values()) {
217             ref.tell(new PrintRole(), null);
218         }
219     }
220
221     public ActorRef getLeader() {
222         return null;
223     }
224
225
226     private static Map<String, String> withoutPeer(String peerId) {
227         Map<String, String> without = new ConcurrentHashMap<>(allPeers);
228         without.remove(peerId);
229
230         return without;
231     }
232 }
233