Merge "Implement cluster wide topology notifications and let routing use it"
[controller.git] / opendaylight / clustering / test / src / main / java / org / opendaylight / controller / clustering / test / internal / SimpleClient.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.clustering.test.internal;
11
12 import java.util.ArrayList;
13 import java.util.EnumSet;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Properties;
17 import java.util.Set;
18 import java.util.concurrent.ConcurrentMap;
19
20 import org.eclipse.osgi.framework.console.CommandInterpreter;
21 import org.eclipse.osgi.framework.console.CommandProvider;
22 import org.opendaylight.controller.clustering.services.CacheConfigException;
23 import org.opendaylight.controller.clustering.services.CacheExistException;
24 import org.opendaylight.controller.clustering.services.CacheListenerAddException;
25 import org.opendaylight.controller.clustering.services.IClusterServices;
26 import org.opendaylight.controller.clustering.services.IGetUpdates;
27 import org.opendaylight.controller.clustering.services.IListenRoleChange;
28 import org.opendaylight.controller.clustering.services.ListenRoleChangeAddException;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 public class SimpleClient implements CommandProvider {
33     protected static Logger logger = LoggerFactory
34             .getLogger(SimpleClient.class);
35     IClusterServices icluster;
36     DoListenRoleChanged doListen;
37
38     public void _tbegin(CommandInterpreter ci) {
39         if (this.icluster == null) {
40             ci.println("\nNo Clustering services available");
41             return;
42         }
43         try {
44             this.icluster.tbegin();
45             ci.println("Transaction Open "
46                     + this.icluster.tgetTransaction().toString());
47         } catch (Exception e) {
48             ci.println("Caught exception during transaction begin: " + e);
49         }
50     }
51
52     public void _tcommit(CommandInterpreter ci) {
53         if (this.icluster == null) {
54             ci.println("\nNo Clustering services available");
55             return;
56         }
57         try {
58             ci.println("Committing transaction ....."
59                     + this.icluster.tgetTransaction().toString());
60             this.icluster.tcommit();
61             ci.println("Transaction Committed");
62         } catch (Exception e) {
63             ci.println("Caught exception during transaction commit: " + e);
64         }
65     }
66
67     public void _trollback(CommandInterpreter ci) {
68         if (this.icluster == null) {
69             ci.println("\nNo Clustering services available");
70             return;
71         }
72         try {
73             ci.println("Rolling back transaction ....."
74                     + this.icluster.tgetTransaction().toString());
75             this.icluster.trollback();
76             ci.println("Transaction Rolled Back");
77         } catch (Exception e) {
78             ci.println("Caught exception during transaction rollback: " + e);
79         }
80     }
81
82     public void _cacheinfo(CommandInterpreter ci) {
83         if (this.icluster == null) {
84             ci.println("\nNo Clustering services available");
85             return;
86         }
87         String containerName = ci.nextArgument();
88         if (containerName == null) {
89             ci.println("containerName not supplied");
90             return;
91         }
92         String cacheName = ci.nextArgument();
93         if (cacheName == null) {
94             ci.println("Cache not supplied");
95             return;
96         }
97         if (!this.icluster.existCache(containerName, cacheName)) {
98             ci.println("\tCache " + cacheName + " doesn't exists");
99             return;
100         }
101         ci.println("\tInfo for cache " + cacheName + " on container "
102                 + containerName);
103         Properties p = this.icluster.getCacheProperties(containerName,
104                 cacheName);
105         if (p != null) {
106             for (String key : p.stringPropertyNames()) {
107                 ci.println("\t\t" + key + " = " + p.getProperty(key));
108             }
109         }
110     }
111
112     public void _setLogLevel(CommandInterpreter ci) {
113         String loggerName = ci.nextArgument();
114         if (loggerName == null) {
115             ci.println("Logger Name not supplied");
116             return;
117         }
118         String loggerLevel = ci.nextArgument();
119         if (loggerLevel == null) {
120             ci.println("Logger Level not supplied");
121             return;
122         }
123
124         ch.qos.logback.classic.Logger l = (ch.qos.logback.classic.Logger) LoggerFactory
125                 .getLogger(loggerName);
126         ch.qos.logback.classic.Level level = ch.qos.logback.classic.Level
127                 .toLevel(loggerLevel);
128         if (level == null) {
129             ci.println("Level not understood");
130             return;
131         }
132         l.setLevel(level);
133     }
134
135     private String retrieveLogLevel(ch.qos.logback.classic.Logger l) {
136         if (l == null) {
137             return ("Logger not supplied");
138         }
139         ch.qos.logback.classic.Level level = l.getLevel();
140         if (level == null) {
141             return ("Logger " + l.getName() + " at unknown level");
142         } else {
143             return ("Logger " + l.getName() + " at level " + l.getLevel()
144                     .toString());
145         }
146     }
147
148     public void _getLogLevel(CommandInterpreter ci) {
149         String loggerName = ci.nextArgument();
150         ch.qos.logback.classic.LoggerContext lc = (ch.qos.logback.classic.LoggerContext) LoggerFactory
151                 .getILoggerFactory();
152         if (lc != null) {
153             for (ch.qos.logback.classic.Logger l : lc.getLoggerList()) {
154                 if ((loggerName == null) || l.getName().startsWith(loggerName)) {
155                     ci.println(retrieveLogLevel(l));
156                 }
157             }
158         }
159     }
160
161     public void _create(CommandInterpreter ci) {
162         if (this.icluster == null) {
163             ci.println("\nNo Clustering services available");
164             return;
165         }
166         String containerName = ci.nextArgument();
167         if (containerName == null) {
168             ci.println("containerName not supplied");
169             return;
170         }
171         String cacheName = ci.nextArgument();
172         if (cacheName == null) {
173             ci.println("Cache not supplied");
174             return;
175         }
176         try {
177             if (cacheName.startsWith("T-")) {
178                 this.icluster.createCache(containerName, cacheName, EnumSet
179                         .of(IClusterServices.cacheMode.TRANSACTIONAL));
180             } else {
181                 this.icluster.createCache(containerName, cacheName, EnumSet
182                         .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
183             }
184         } catch (CacheExistException ce) {
185             ci
186                     .println("\nCache already exits - destroy and recreate if needed");
187             return;
188         } catch (CacheConfigException cfe) {
189             ci.println("\nCache configured with contrasting parameters");
190             return;
191         }
192
193         if (this.icluster.existCache(containerName, cacheName)) {
194             ci.println(cacheName + " has been created on container "
195                     + containerName);
196         }
197     }
198
199     public void _destroy(CommandInterpreter ci) {
200         if (this.icluster == null) {
201             ci.println("\nNo Clustering services available");
202             return;
203         }
204         String containerName = ci.nextArgument();
205         if (containerName == null) {
206             ci.println("containerName not supplied");
207             return;
208         }
209         String cacheName = ci.nextArgument();
210         if (cacheName == null) {
211             ci.println("Cache not supplied");
212             return;
213         }
214         if (this.icluster.existCache(containerName, cacheName)) {
215             this.icluster.destroyCache(containerName, cacheName);
216             ci.println(cacheName + " has been destroyed");
217         }
218     }
219
220     public void _listen(CommandInterpreter ci) {
221         if (this.icluster == null) {
222             ci.println("\nNo Clustering services available");
223             return;
224         }
225         String containerName = ci.nextArgument();
226         if (containerName == null) {
227             ci.println("containerName not supplied");
228             return;
229         }
230         String cacheName = ci.nextArgument();
231         if (cacheName == null) {
232             ci.println("Cache not supplied");
233             return;
234         }
235         try {
236             this.icluster.addListener(containerName, cacheName,
237                     new LoggingListener());
238             ci.println("cache " + cacheName + " on container " + containerName
239                     + " is begin monitored for updates");
240         } catch (CacheListenerAddException clae) {
241             ci.println("Couldn't attach the listener to cache " + cacheName
242                     + " on container " + containerName);
243         }
244     }
245
246     @SuppressWarnings("deprecation") //IGetUpdates intentionally deprecated
247     public void _unlisten(CommandInterpreter ci) {
248         if (this.icluster == null) {
249             ci.println("\nNo Clustering services available");
250             return;
251         }
252         String containerName = ci.nextArgument();
253         if (containerName == null) {
254             ci.println("containerName not supplied");
255             return;
256         }
257         String cacheName = ci.nextArgument();
258         if (cacheName == null) {
259             ci.println("Cache not supplied");
260             return;
261         }
262
263         Set<IGetUpdates<?, ?>> listeners = this.icluster.getListeners(
264                 containerName, cacheName);
265         for (IGetUpdates<?, ?> l : listeners) {
266             this.icluster.removeListener(containerName, cacheName, l);
267         }
268         ci.println(cacheName + " is no longer being monitored for updates");
269     }
270
271     public void _listcaches(CommandInterpreter ci) {
272         if (this.icluster == null) {
273             ci.println("\nNo Clustering services available");
274             return;
275         }
276         String containerName = ci.nextArgument().toLowerCase();
277         if (containerName == null) {
278             ci.println("containerName not supplied");
279             return;
280         }
281
282         // For user's convenience, let's return the sorted cache list
283         List<String> sortedCacheList = new ArrayList<String>(this.icluster
284                 .getCacheList(containerName));
285         java.util.Collections.sort(sortedCacheList);
286         for (String cacheName : sortedCacheList) {
287             ci.println("\t" + cacheName);
288         }
289     }
290
291     public void _put(CommandInterpreter ci) {
292         ConcurrentMap<Integer, StringContainer> c;
293         if (this.icluster == null) {
294             ci.println("\nNo Clustering services available");
295             return;
296         }
297         String containerName = ci.nextArgument();
298         if (containerName == null) {
299             ci.println("containerName not supplied");
300             return;
301         }
302         String cacheName = ci.nextArgument();
303         if (cacheName == null) {
304             ci.println("Cache not supplied");
305             return;
306         }
307         String sKey = ci.nextArgument();
308         String sValue = ci.nextArgument();
309         if (sKey == null) {
310             ci.println("Key not supplied");
311             return;
312         }
313         if (sValue == null) {
314             ci.println("Value not supplied");
315             return;
316         }
317         Integer key = null;
318         try {
319             key = Integer.valueOf(sKey);
320         } catch (NumberFormatException nfe) {
321             ci.println("Key is not a valid integer: " + sKey);
322         }
323
324         c = (ConcurrentMap<Integer, StringContainer>) this.icluster.getCache(
325                 containerName, cacheName);
326         if (c != null) {
327             ci.println("\nAdd mapping " + key + " = " + sValue);
328             c.put(key, new StringContainer(sValue));
329         } else {
330             ci.println("Cache " + cacheName + " on container " + containerName
331                     + " not existant!");
332         }
333     }
334
335     public void _remove(CommandInterpreter ci) {
336         ConcurrentMap<Integer, StringContainer> c;
337         if (this.icluster == null) {
338             ci.println("\nNo Clustering services available");
339             return;
340         }
341         String containerName = ci.nextArgument();
342         if (containerName == null) {
343             ci.println("containerName not supplied");
344             return;
345         }
346         String cacheName = ci.nextArgument();
347         if (cacheName == null) {
348             ci.println("Cache not supplied");
349             return;
350         }
351         String sKey = ci.nextArgument();
352         if (sKey == null) {
353             ci.println("Key not supplied");
354             return;
355         }
356         Integer key = null;
357         try {
358             key = Integer.valueOf(sKey);
359         } catch (NumberFormatException nfe) {
360             ci.println("Key is not a valid integer: " + sKey);
361         }
362         c = (ConcurrentMap<Integer, StringContainer>) this.icluster.getCache(
363                 containerName, cacheName);
364         if (c != null) {
365             ci.println("\nDelete key " + key);
366             c.remove(key);
367         } else {
368             ci.println("Cache " + cacheName + " on container " + containerName
369                     + " not existant!");
370         }
371     }
372
373     public void _dumper(CommandInterpreter ci) {
374         ConcurrentMap<Object, Object> c;
375         String containerName = ci.nextArgument().toLowerCase();
376         if (containerName == null) {
377             ci.println("containerName not supplied");
378             return;
379         }
380         String cacheName = ci.nextArgument();
381         if (cacheName == null) {
382             ci.println("Cache not supplied");
383             return;
384         }
385         int count = 0;
386         c = (ConcurrentMap<Object, Object>) this.icluster.getCache(containerName, cacheName);
387         if (c != null) {
388             for (Map.Entry<Object, Object> e : c.entrySet()) {
389                 Map.Entry<Object, Object> entry = e;
390                 Object v = entry.getValue();
391                 String res = "<NOT KNOWN>";
392                 if (v != null) {
393                     res = v.toString();
394                 }
395                 ci.println("Element " + entry.getKey() + "(hashCode="
396                         + entry.getKey().hashCode() + ") has value = (" + res
397                         + ")");
398                 count++;
399             }
400             ci.println("Dumped " + count + " records");
401         } else {
402             ci.println("Cache " + cacheName + " on container " + containerName
403                     + " not existant!");
404         }
405     }
406
407     public void _get(CommandInterpreter ci) {
408         ConcurrentMap<Integer, StringContainer> c;
409         if (this.icluster == null) {
410             ci.println("\nNo Clustering services available");
411             return;
412         }
413         String containerName = ci.nextArgument();
414         if (containerName == null) {
415             ci.println("containerName not supplied");
416             return;
417         }
418         String cacheName = ci.nextArgument();
419         if (cacheName == null) {
420             ci.println("Cache not supplied");
421             return;
422         }
423         String sKey = ci.nextArgument();
424         if (sKey == null) {
425             ci.println("Key not supplied");
426             return;
427         }
428         Integer key = null;
429         try {
430             key = Integer.valueOf(sKey);
431         } catch (NumberFormatException nfe) {
432             ci.println("Key is not a valid integer: " + sKey);
433         }
434         c = (ConcurrentMap<Integer, StringContainer>) this.icluster.getCache(
435                 containerName, cacheName);
436         if (c != null) {
437             ci.println("\nGet key (" + key + ")=(" + c.get(key) + ")");
438         } else {
439             ci.println("Cache " + cacheName + " on container " + containerName
440                     + " not existant!");
441         }
442     }
443
444     @SuppressWarnings("deprecation") //TODO: remove call to deprecated amIStandby
445     public void _getRole(CommandInterpreter ci) {
446         if (this.icluster == null) {
447             ci.println("\nNo Clustering services available");
448             return;
449         }
450         String role = "Active";
451         if (this.icluster.amIStandby()) {
452             role = "Standby";
453         }
454         ci.println("My role is: " + role);
455     }
456
457     @SuppressWarnings("deprecation") //TODO: remove call to deprecated getActiveAddres
458     public void _getActive(CommandInterpreter ci) {
459         if (this.icluster == null) {
460             ci.println("\nNo Clustering services available");
461             return;
462         }
463         ci.println("Current active address is "
464                 + this.icluster.getActiveAddress());
465     }
466
467     @SuppressWarnings("deprecation") //TODO: remove use of deprecated listenRoleChange
468     public void _listenActive(CommandInterpreter ci) {
469         if (this.icluster == null) {
470             ci.println("\nNo Clustering services available");
471             return;
472         }
473         this.doListen = new DoListenRoleChanged();
474         try {
475             this.icluster.listenRoleChange(this.doListen);
476         } catch (ListenRoleChangeAddException e) {
477             ci.println("Exception while registering the listener");
478             return;
479         }
480         ci.println("Register listenRoleChanges");
481     }
482
483     @SuppressWarnings("deprecation") //TODO: remove deprecated call to unlistenRoleChange
484     public void _unlistenActive(CommandInterpreter ci) {
485         if (this.icluster == null) {
486             ci.println("\nNo Clustering services available");
487             return;
488         }
489         if (this.doListen != null) {
490             this.icluster.unlistenRoleChange(this.doListen);
491             ci.println("Unregistered Active notifications");
492         }
493     }
494
495     class DoListenRoleChanged implements IListenRoleChange {
496         @Override
497         public void newActiveAvailable() {
498             logger.debug("New Active is available");
499         }
500     }
501
502     public void _putComplex(CommandInterpreter ci) {
503         ConcurrentMap<StringContainer, ComplexContainer> c;
504         if (this.icluster == null) {
505             ci.println("\nNo Clustering services available");
506             return;
507         }
508         String containerName = ci.nextArgument();
509         if (containerName == null) {
510             ci.println("containerName not supplied");
511             return;
512         }
513         String cacheName = ci.nextArgument();
514         if (cacheName == null) {
515             ci.println("Cache not supplied");
516             return;
517         }
518         String key = ci.nextArgument();
519         if (key == null) {
520             ci.println("Key not supplied (String)");
521             return;
522         }
523         String valueIdentity = ci.nextArgument();
524         if (valueIdentity == null) {
525             ci.println("Value for Identity not supplied (String)");
526             return;
527         }
528         String sValueState = ci.nextArgument();
529         if (sValueState == null) {
530             ci.println("Value for State not supplied (Integer)");
531             return;
532         }
533         Integer valueState = null;
534         try {
535             valueState = Integer.valueOf(sValueState);
536         } catch (NumberFormatException nfe) {
537             ci.println("Value State is not a valid integer: " + sValueState);
538             return;
539         }
540         c = (ConcurrentMap<StringContainer, ComplexContainer>) this.icluster
541                 .getCache(containerName, cacheName);
542         if (c != null) {
543             c.put(new StringContainer(key), new ComplexContainer(valueIdentity,
544                     valueState));
545             ci.println("\nPut in key (" + key + ")={String:" + valueIdentity
546                     + ",Integer:" + valueState + "}");
547         } else {
548             ci.println("Cache " + cacheName + " on container " + containerName
549                     + " not existant!");
550         }
551     }
552
553     public void _updateComplex(CommandInterpreter ci) {
554         ConcurrentMap<StringContainer, ComplexContainer> c;
555         if (this.icluster == null) {
556             ci.println("\nNo Clustering services available");
557             return;
558         }
559         String containerName = ci.nextArgument();
560         if (containerName == null) {
561             ci.println("containerName not supplied");
562             return;
563         }
564         String cacheName = ci.nextArgument();
565         if (cacheName == null) {
566             ci.println("Cache not supplied");
567             return;
568         }
569         String key = ci.nextArgument();
570         if (key == null) {
571             ci.println("Key not supplied (String)");
572             return;
573         }
574         String valueIdentity = ci.nextArgument();
575         if (valueIdentity == null) {
576             ci.println("Value for Identity not supplied (String)");
577             return;
578         }
579         c = (ConcurrentMap<StringContainer, ComplexContainer>) this.icluster
580                 .getCache(containerName, cacheName);
581         if (c != null) {
582             StringContainer k = new StringContainer(key);
583             ComplexContainer v = c.get(k);
584             if (v != null) {
585                 v.setIdentity(valueIdentity);
586                 ci.println("\nUpdate key (" + key + ")={String:"
587                         + valueIdentity + "}");
588
589                 // IMPORTANT ON UPDATING ANY FIELD OF THE CHILD MAKE
590                 // SURE TO PUT THE NEW VALUE IN THE CACHE ELSE THE
591                 // VALUE WILL NOT PROPAGATE!!
592                 c.put(k, v);
593             } else {
594                 ci.println("\nCannot Update key (" + key
595                         + ") doesn't exist in the database");
596             }
597         } else {
598             ci.println("Cache " + cacheName + " on container " + containerName
599                     + " not existant!");
600         }
601     }
602
603     public void setIClusterServices(IClusterServices i) {
604         this.icluster = i;
605         logger.debug("IClusterServices set");
606     }
607
608     public void unsetIClusterServices(IClusterServices i) {
609         if (this.icluster == i) {
610             this.icluster = null;
611             logger.debug("IClusterServices UNset");
612         }
613     }
614
615     public void startUp() {
616         logger.debug("Started clustering test plugin");
617     }
618
619     public void shutDown() {
620         logger.debug("Stopped clustering test plugin");
621     }
622
623     @Override
624     public String getHelp() {
625         StringBuffer help = new StringBuffer();
626         help.append("---Clustering Service Testing---\n");
627         help.append("\tput              - Put a key,value in the cache\n");
628         help.append("\tremove           - Delete a key from the cache\n");
629         help.append("\tget              - Get a key from the cache\n");
630         help.append("\tdumper           - Dump the cache\n");
631         help
632                 .append("\tcacheinfo        - Dump the configuration for a cache\n");
633         help.append("\ttbegin           - Transaction begin\n");
634         help.append("\ttcommit          - Transaction Commit\n");
635         help.append("\ttrollback        - Transaction Rollback\n");
636         help.append("\tlistcaches       - List all the Caches\n");
637         help.append("\tlisten           - Listen to cache updates\n");
638         help.append("\tunlisten         - UNListen to cache updates\n");
639         help.append("\tlistenActive     - Listen to Active updates\n");
640         help.append("\tunlistenActive   - UNListen to Active updates\n");
641         help.append("\tdestroy          - Destroy a cache\n");
642         help.append("\tcreate           - Create a cache\n");
643         help.append("\tgetRole          - Tell if active or standby\n");
644         help.append("\tgetActive        - Report the IP address of Active\n");
645         help
646                 .append("\tputComplex       - Fill a more complex data structure\n");
647         help
648                 .append("\tupdateComplex    - Update the value of a more complex data structure\n");
649         help
650                 .append("\tgetLogLevel      - Get the loglevel for the logger specified\n");
651         help
652                 .append("\tsetLogLevel      - Set the loglevel for the logger specified\n");
653         return help.toString();
654     }
655 }