3 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
10 package org.opendaylight.controller.clustering.test.internal;
12 import java.net.InetAddress;
13 import java.util.ArrayList;
14 import java.util.EnumSet;
15 import java.util.List;
17 import java.util.Properties;
19 import java.util.concurrent.ConcurrentMap;
21 import org.eclipse.osgi.framework.console.CommandInterpreter;
22 import org.eclipse.osgi.framework.console.CommandProvider;
23 import org.opendaylight.controller.clustering.services.CacheConfigException;
24 import org.opendaylight.controller.clustering.services.CacheExistException;
25 import org.opendaylight.controller.clustering.services.CacheListenerAddException;
26 import org.opendaylight.controller.clustering.services.IClusterServices;
27 import org.opendaylight.controller.clustering.services.IGetUpdates;
28 import org.opendaylight.controller.clustering.services.IListenRoleChange;
29 import org.opendaylight.controller.clustering.services.ListenRoleChangeAddException;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 public class SimpleClient implements CommandProvider {
34 protected static Logger logger = LoggerFactory
35 .getLogger(SimpleClient.class);
36 IClusterServices icluster;
37 DoListenRoleChanged doListen;
39 public void _tbegin(CommandInterpreter ci) {
40 if (this.icluster == null) {
41 ci.println("\nNo Clustering services available");
45 this.icluster.tbegin();
46 ci.println("Transaction Open "
47 + this.icluster.tgetTransaction().toString());
48 } catch (Exception e) {
49 ci.println("Caught exception during transaction begin: " + e);
53 public void _tcommit(CommandInterpreter ci) {
54 if (this.icluster == null) {
55 ci.println("\nNo Clustering services available");
59 ci.println("Committing transaction ....."
60 + this.icluster.tgetTransaction().toString());
61 this.icluster.tcommit();
62 ci.println("Transaction Committed");
63 } catch (Exception e) {
64 ci.println("Caught exception during transaction commit: " + e);
68 public void _trollback(CommandInterpreter ci) {
69 if (this.icluster == null) {
70 ci.println("\nNo Clustering services available");
74 ci.println("Rolling back transaction ....."
75 + this.icluster.tgetTransaction().toString());
76 this.icluster.trollback();
77 ci.println("Transaction Rolled Back");
78 } catch (Exception e) {
79 ci.println("Caught exception during transaction rollback: " + e);
83 public void _cacheinfo(CommandInterpreter ci) {
84 if (this.icluster == null) {
85 ci.println("\nNo Clustering services available");
88 String containerName = ci.nextArgument();
89 if (containerName == null) {
90 ci.println("containerName not supplied");
93 String cacheName = ci.nextArgument();
94 if (cacheName == null) {
95 ci.println("Cache not supplied");
98 if (!this.icluster.existCache(containerName, cacheName)) {
99 ci.println("\tCache " + cacheName + " doesn't exists");
102 ci.println("\tInfo for cache " + cacheName + " on container "
104 Properties p = this.icluster.getCacheProperties(containerName,
107 for (String key : p.stringPropertyNames()) {
108 ci.println("\t\t" + key + " = " + p.getProperty(key));
113 public void _setLogLevel(CommandInterpreter ci) {
114 String loggerName = ci.nextArgument();
115 if (loggerName == null) {
116 ci.println("Logger Name not supplied");
119 String loggerLevel = ci.nextArgument();
120 if (loggerLevel == null) {
121 ci.println("Logger Level not supplied");
125 ch.qos.logback.classic.Logger l = (ch.qos.logback.classic.Logger) LoggerFactory
126 .getLogger(loggerName);
127 ch.qos.logback.classic.Level level = ch.qos.logback.classic.Level
128 .toLevel(loggerLevel);
130 ci.println("Level not understood");
136 private String retrieveLogLevel(ch.qos.logback.classic.Logger l) {
138 return ("Logger not supplied");
140 ch.qos.logback.classic.Level level = l.getLevel();
142 return ("Logger " + l.getName() + " at unknown level");
144 return ("Logger " + l.getName() + " at level " + l.getLevel()
149 public void _getLogLevel(CommandInterpreter ci) {
150 String loggerName = ci.nextArgument();
151 ch.qos.logback.classic.LoggerContext lc = (ch.qos.logback.classic.LoggerContext) LoggerFactory
152 .getILoggerFactory();
154 for (ch.qos.logback.classic.Logger l : lc.getLoggerList()) {
155 if ((loggerName == null) || l.getName().startsWith(loggerName)) {
156 ci.println(retrieveLogLevel(l));
162 public void _create(CommandInterpreter ci) {
163 if (this.icluster == null) {
164 ci.println("\nNo Clustering services available");
167 String containerName = ci.nextArgument();
168 if (containerName == null) {
169 ci.println("containerName not supplied");
172 String cacheName = ci.nextArgument();
173 if (cacheName == null) {
174 ci.println("Cache not supplied");
178 if (cacheName.startsWith("T-")) {
179 this.icluster.createCache(containerName, cacheName, EnumSet
180 .of(IClusterServices.cacheMode.TRANSACTIONAL));
182 this.icluster.createCache(containerName, cacheName, EnumSet
183 .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
185 } catch (CacheExistException ce) {
187 .println("\nCache already exits - destroy and recreate if needed");
189 } catch (CacheConfigException cfe) {
190 ci.println("\nCache configured with contrasting parameters");
194 if (this.icluster.existCache(containerName, cacheName)) {
195 ci.println(cacheName + " has been created on container "
200 public void _destroy(CommandInterpreter ci) {
201 if (this.icluster == null) {
202 ci.println("\nNo Clustering services available");
205 String containerName = ci.nextArgument();
206 if (containerName == null) {
207 ci.println("containerName not supplied");
210 String cacheName = ci.nextArgument();
211 if (cacheName == null) {
212 ci.println("Cache not supplied");
215 if (this.icluster.existCache(containerName, cacheName)) {
216 this.icluster.destroyCache(containerName, cacheName);
217 ci.println(cacheName + " has been destroyed");
221 public void _listen(CommandInterpreter ci) {
222 if (this.icluster == null) {
223 ci.println("\nNo Clustering services available");
226 String containerName = ci.nextArgument();
227 if (containerName == null) {
228 ci.println("containerName not supplied");
231 String cacheName = ci.nextArgument();
232 if (cacheName == null) {
233 ci.println("Cache not supplied");
237 this.icluster.addListener(containerName, cacheName,
238 new LoggingListener());
239 ci.println("cache " + cacheName + " on container " + containerName
240 + " is begin monitored for updates");
241 } catch (CacheListenerAddException clae) {
242 ci.println("Couldn't attach the listener to cache " + cacheName
243 + " on container " + containerName);
247 @SuppressWarnings("deprecation") //IGetUpdates intentionally deprecated
248 public void _unlisten(CommandInterpreter ci) {
249 if (this.icluster == null) {
250 ci.println("\nNo Clustering services available");
253 String containerName = ci.nextArgument();
254 if (containerName == null) {
255 ci.println("containerName not supplied");
258 String cacheName = ci.nextArgument();
259 if (cacheName == null) {
260 ci.println("Cache not supplied");
264 Set<IGetUpdates<?, ?>> listeners = this.icluster.getListeners(
265 containerName, cacheName);
266 for (IGetUpdates<?, ?> l : listeners) {
267 this.icluster.removeListener(containerName, cacheName, l);
269 ci.println(cacheName + " is no longer being monitored for updates");
272 public void _myController(CommandInterpreter ci) {
273 if (this.icluster == null) {
274 ci.println("\nNo Clustering services available");
277 ci.println("This Controller : " +icluster.getMyAddress().getHostAddress());
280 public void _getClusterNodes(CommandInterpreter ci) {
281 if (this.icluster == null) {
282 ci.println("\nNo Clustering services available");
285 for (InetAddress address : icluster.getClusteredControllers()) {
286 ci.println("\t"+address.getHostAddress());
290 public void _listcaches(CommandInterpreter ci) {
291 if (this.icluster == null) {
292 ci.println("\nNo Clustering services available");
295 String containerName = ci.nextArgument().toLowerCase();
296 if (containerName == null) {
297 ci.println("containerName not supplied");
301 // For user's convenience, let's return the sorted cache list
302 List<String> sortedCacheList = new ArrayList<String>(this.icluster
303 .getCacheList(containerName));
304 java.util.Collections.sort(sortedCacheList);
305 for (String cacheName : sortedCacheList) {
306 ci.println("\t" + cacheName);
310 public void _put(CommandInterpreter ci) {
311 ConcurrentMap<Integer, StringContainer> c;
312 if (this.icluster == null) {
313 ci.println("\nNo Clustering services available");
316 String containerName = ci.nextArgument();
317 if (containerName == null) {
318 ci.println("containerName not supplied");
321 String cacheName = ci.nextArgument();
322 if (cacheName == null) {
323 ci.println("Cache not supplied");
326 String sKey = ci.nextArgument();
327 String sValue = ci.nextArgument();
329 ci.println("Key not supplied");
332 if (sValue == null) {
333 ci.println("Value not supplied");
338 key = Integer.valueOf(sKey);
339 } catch (NumberFormatException nfe) {
340 ci.println("Key is not a valid integer: " + sKey);
343 c = (ConcurrentMap<Integer, StringContainer>) this.icluster.getCache(
344 containerName, cacheName);
346 ci.println("\nAdd mapping " + key + " = " + sValue);
347 c.put(key, new StringContainer(sValue));
349 ci.println("Cache " + cacheName + " on container " + containerName
354 public void _remove(CommandInterpreter ci) {
355 ConcurrentMap<Integer, StringContainer> c;
356 if (this.icluster == null) {
357 ci.println("\nNo Clustering services available");
360 String containerName = ci.nextArgument();
361 if (containerName == null) {
362 ci.println("containerName not supplied");
365 String cacheName = ci.nextArgument();
366 if (cacheName == null) {
367 ci.println("Cache not supplied");
370 String sKey = ci.nextArgument();
372 ci.println("Key not supplied");
377 key = Integer.valueOf(sKey);
378 } catch (NumberFormatException nfe) {
379 ci.println("Key is not a valid integer: " + sKey);
381 c = (ConcurrentMap<Integer, StringContainer>) this.icluster.getCache(
382 containerName, cacheName);
384 ci.println("\nDelete key " + key);
387 ci.println("Cache " + cacheName + " on container " + containerName
392 public void _dumper(CommandInterpreter ci) {
393 ConcurrentMap<Object, Object> c;
394 String containerName = ci.nextArgument().toLowerCase();
395 if (containerName == null) {
396 ci.println("containerName not supplied");
399 String cacheName = ci.nextArgument();
400 if (cacheName == null) {
401 ci.println("Cache not supplied");
405 c = (ConcurrentMap<Object, Object>) this.icluster.getCache(containerName, cacheName);
407 for (Map.Entry<Object, Object> e : c.entrySet()) {
408 Map.Entry<Object, Object> entry = e;
409 Object v = entry.getValue();
410 String res = "<NOT KNOWN>";
414 ci.println("Element " + entry.getKey() + "(hashCode="
415 + entry.getKey().hashCode() + ") has value = (" + res
419 ci.println("Dumped " + count + " records");
421 ci.println("Cache " + cacheName + " on container " + containerName
426 public void _get(CommandInterpreter ci) {
427 ConcurrentMap<Integer, StringContainer> c;
428 if (this.icluster == null) {
429 ci.println("\nNo Clustering services available");
432 String containerName = ci.nextArgument();
433 if (containerName == null) {
434 ci.println("containerName not supplied");
437 String cacheName = ci.nextArgument();
438 if (cacheName == null) {
439 ci.println("Cache not supplied");
442 String sKey = ci.nextArgument();
444 ci.println("Key not supplied");
449 key = Integer.valueOf(sKey);
450 } catch (NumberFormatException nfe) {
451 ci.println("Key is not a valid integer: " + sKey);
453 c = (ConcurrentMap<Integer, StringContainer>) this.icluster.getCache(
454 containerName, cacheName);
456 ci.println("\nGet key (" + key + ")=(" + c.get(key) + ")");
458 ci.println("Cache " + cacheName + " on container " + containerName
463 @SuppressWarnings("deprecation") //TODO: remove use of deprecated listenRoleChange
464 public void _listenActive(CommandInterpreter ci) {
465 if (this.icluster == null) {
466 ci.println("\nNo Clustering services available");
469 this.doListen = new DoListenRoleChanged();
471 this.icluster.listenRoleChange(this.doListen);
472 } catch (ListenRoleChangeAddException e) {
473 ci.println("Exception while registering the listener");
476 ci.println("Register listenRoleChanges");
479 @SuppressWarnings("deprecation") //TODO: remove deprecated call to unlistenRoleChange
480 public void _unlistenActive(CommandInterpreter ci) {
481 if (this.icluster == null) {
482 ci.println("\nNo Clustering services available");
485 if (this.doListen != null) {
486 this.icluster.unlistenRoleChange(this.doListen);
487 ci.println("Unregistered Active notifications");
491 class DoListenRoleChanged implements IListenRoleChange {
493 public void newActiveAvailable() {
494 logger.debug("New Active is available");
498 public void _putComplex(CommandInterpreter ci) {
499 ConcurrentMap<StringContainer, ComplexContainer> c;
500 if (this.icluster == null) {
501 ci.println("\nNo Clustering services available");
504 String containerName = ci.nextArgument();
505 if (containerName == null) {
506 ci.println("containerName not supplied");
509 String cacheName = ci.nextArgument();
510 if (cacheName == null) {
511 ci.println("Cache not supplied");
514 String key = ci.nextArgument();
516 ci.println("Key not supplied (String)");
519 String valueIdentity = ci.nextArgument();
520 if (valueIdentity == null) {
521 ci.println("Value for Identity not supplied (String)");
524 String sValueState = ci.nextArgument();
525 if (sValueState == null) {
526 ci.println("Value for State not supplied (Integer)");
529 Integer valueState = null;
531 valueState = Integer.valueOf(sValueState);
532 } catch (NumberFormatException nfe) {
533 ci.println("Value State is not a valid integer: " + sValueState);
536 c = (ConcurrentMap<StringContainer, ComplexContainer>) this.icluster
537 .getCache(containerName, cacheName);
539 c.put(new StringContainer(key), new ComplexContainer(valueIdentity,
541 ci.println("\nPut in key (" + key + ")={String:" + valueIdentity
542 + ",Integer:" + valueState + "}");
544 ci.println("Cache " + cacheName + " on container " + containerName
549 public void _updateComplex(CommandInterpreter ci) {
550 ConcurrentMap<StringContainer, ComplexContainer> c;
551 if (this.icluster == null) {
552 ci.println("\nNo Clustering services available");
555 String containerName = ci.nextArgument();
556 if (containerName == null) {
557 ci.println("containerName not supplied");
560 String cacheName = ci.nextArgument();
561 if (cacheName == null) {
562 ci.println("Cache not supplied");
565 String key = ci.nextArgument();
567 ci.println("Key not supplied (String)");
570 String valueIdentity = ci.nextArgument();
571 if (valueIdentity == null) {
572 ci.println("Value for Identity not supplied (String)");
575 c = (ConcurrentMap<StringContainer, ComplexContainer>) this.icluster
576 .getCache(containerName, cacheName);
578 StringContainer k = new StringContainer(key);
579 ComplexContainer v = c.get(k);
581 v.setIdentity(valueIdentity);
582 ci.println("\nUpdate key (" + key + ")={String:"
583 + valueIdentity + "}");
585 // IMPORTANT ON UPDATING ANY FIELD OF THE CHILD MAKE
586 // SURE TO PUT THE NEW VALUE IN THE CACHE ELSE THE
587 // VALUE WILL NOT PROPAGATE!!
590 ci.println("\nCannot Update key (" + key
591 + ") doesn't exist in the database");
594 ci.println("Cache " + cacheName + " on container " + containerName
599 public void setIClusterServices(IClusterServices i) {
601 logger.debug("IClusterServices set");
604 public void unsetIClusterServices(IClusterServices i) {
605 if (this.icluster == i) {
606 this.icluster = null;
607 logger.debug("IClusterServices UNset");
611 public void startUp() {
612 logger.debug("Started clustering test plugin");
615 public void shutDown() {
616 logger.debug("Stopped clustering test plugin");
620 public String getHelp() {
621 StringBuffer help = new StringBuffer();
622 help.append("---Clustering Service Testing---\n");
623 help.append("\tput - Put a key,value in the cache\n");
624 help.append("\tremove - Delete a key from the cache\n");
625 help.append("\tget - Get a key from the cache\n");
626 help.append("\tdumper - Dump the cache\n");
628 .append("\tcacheinfo - Dump the configuration for a cache\n");
629 help.append("\ttbegin - Transaction begin\n");
630 help.append("\ttcommit - Transaction Commit\n");
631 help.append("\ttrollback - Transaction Rollback\n");
632 help.append("\tlistcaches - List all the Caches\n");
633 help.append("\tlisten - Listen to cache updates\n");
634 help.append("\tunlisten - UNListen to cache updates\n");
635 help.append("\tlistenActive - Listen to Active updates\n");
636 help.append("\tunlistenActive - UNListen to Active updates\n");
637 help.append("\tdestroy - Destroy a cache\n");
638 help.append("\tcreate - Create a cache\n");
639 help.append("\tmyController - Print this controller's Cluster identifier\n");
640 help.append("\tgetClusterNodes - Print all the controllers that make this cluster\n");
641 help.append("\tputComplex - Fill a more complex data structure\n");
642 help.append("\tupdateComplex - Update the value of a more complex data structure\n");
643 help.append("\tgetLogLevel - Get the loglevel for the logger specified\n");
644 help.append("\tsetLogLevel - Set the loglevel for the logger specified\n");
645 return help.toString();