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.util.ArrayList;
13 import java.util.EnumSet;
14 import java.util.List;
16 import java.util.Properties;
18 import java.util.concurrent.ConcurrentMap;
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;
32 public class SimpleClient implements CommandProvider {
33 protected static Logger logger = LoggerFactory
34 .getLogger(SimpleClient.class);
35 IClusterServices icluster;
36 DoListenRoleChanged doListen;
38 public void _tbegin(CommandInterpreter ci) {
39 if (this.icluster == null) {
40 ci.println("\nNo Clustering services available");
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);
52 public void _tcommit(CommandInterpreter ci) {
53 if (this.icluster == null) {
54 ci.println("\nNo Clustering services available");
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);
67 public void _trollback(CommandInterpreter ci) {
68 if (this.icluster == null) {
69 ci.println("\nNo Clustering services available");
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);
82 public void _cacheinfo(CommandInterpreter ci) {
83 if (this.icluster == null) {
84 ci.println("\nNo Clustering services available");
87 String containerName = ci.nextArgument();
88 if (containerName == null) {
89 ci.println("containerName not supplied");
92 String cacheName = ci.nextArgument();
93 if (cacheName == null) {
94 ci.println("Cache not supplied");
97 if (!this.icluster.existCache(containerName, cacheName)) {
98 ci.println("\tCache " + cacheName + " doesn't exists");
101 ci.println("\tInfo for cache " + cacheName + " on container "
103 Properties p = this.icluster.getCacheProperties(containerName,
106 for (String key : p.stringPropertyNames()) {
107 ci.println("\t\t" + key + " = " + p.getProperty(key));
112 public void _setLogLevel(CommandInterpreter ci) {
113 String loggerName = ci.nextArgument();
114 if (loggerName == null) {
115 ci.println("Logger Name not supplied");
118 String loggerLevel = ci.nextArgument();
119 if (loggerLevel == null) {
120 ci.println("Logger Level not supplied");
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);
129 ci.println("Level not understood");
135 private String retrieveLogLevel(ch.qos.logback.classic.Logger l) {
137 return ("Logger not supplied");
139 ch.qos.logback.classic.Level level = l.getLevel();
141 return ("Logger " + l.getName() + " at unknown level");
143 return ("Logger " + l.getName() + " at level " + l.getLevel()
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();
153 for (ch.qos.logback.classic.Logger l : lc.getLoggerList()) {
154 if (loggerName == null || l.getName().startsWith(loggerName)) {
155 ci.println(retrieveLogLevel(l));
161 public void _create(CommandInterpreter ci) {
162 if (this.icluster == null) {
163 ci.println("\nNo Clustering services available");
166 String containerName = ci.nextArgument();
167 if (containerName == null) {
168 ci.println("containerName not supplied");
171 String cacheName = ci.nextArgument();
172 if (cacheName == null) {
173 ci.println("Cache not supplied");
177 if (cacheName.startsWith("T-")) {
178 this.icluster.createCache(containerName, cacheName, EnumSet
179 .of(IClusterServices.cacheMode.TRANSACTIONAL));
181 this.icluster.createCache(containerName, cacheName, EnumSet
182 .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
184 } catch (CacheExistException ce) {
186 .println("\nCache already exits - destroy and recreate if needed");
188 } catch (CacheConfigException cfe) {
189 ci.println("\nCache configured with contrasting parameters");
193 if (this.icluster.existCache(containerName, cacheName)) {
194 ci.println(cacheName + " has been created on container "
199 public void _destroy(CommandInterpreter ci) {
200 if (this.icluster == null) {
201 ci.println("\nNo Clustering services available");
204 String containerName = ci.nextArgument();
205 if (containerName == null) {
206 ci.println("containerName not supplied");
209 String cacheName = ci.nextArgument();
210 if (cacheName == null) {
211 ci.println("Cache not supplied");
214 if (this.icluster.existCache(containerName, cacheName)) {
215 this.icluster.destroyCache(containerName, cacheName);
216 ci.println(cacheName + " has been destroyed");
220 public void _listen(CommandInterpreter ci) {
221 if (this.icluster == null) {
222 ci.println("\nNo Clustering services available");
225 String containerName = ci.nextArgument();
226 if (containerName == null) {
227 ci.println("containerName not supplied");
230 String cacheName = ci.nextArgument();
231 if (cacheName == null) {
232 ci.println("Cache not supplied");
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);
246 @SuppressWarnings("deprecation") //IGetUpdates intentionally deprecated
247 public void _unlisten(CommandInterpreter ci) {
248 if (this.icluster == null) {
249 ci.println("\nNo Clustering services available");
252 String containerName = ci.nextArgument();
253 if (containerName == null) {
254 ci.println("containerName not supplied");
257 String cacheName = ci.nextArgument();
258 if (cacheName == null) {
259 ci.println("Cache not supplied");
263 Set<IGetUpdates<?, ?>> listeners = this.icluster.getListeners(
264 containerName, cacheName);
265 for (IGetUpdates<?, ?> l : listeners) {
266 this.icluster.removeListener(containerName, cacheName, l);
268 ci.println(cacheName + " is no longer being monitored for updates");
271 public void _listcaches(CommandInterpreter ci) {
272 if (this.icluster == null) {
273 ci.println("\nNo Clustering services available");
276 String containerName = ci.nextArgument();
277 if (containerName == null) {
278 ci.println("containerName not supplied");
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);
291 public void _put(CommandInterpreter ci) {
292 ConcurrentMap<Integer, StringContainer> c;
293 if (this.icluster == null) {
294 ci.println("\nNo Clustering services available");
297 String containerName = ci.nextArgument();
298 if (containerName == null) {
299 ci.println("containerName not supplied");
302 String cacheName = ci.nextArgument();
303 if (cacheName == null) {
304 ci.println("Cache not supplied");
307 String sKey = ci.nextArgument();
308 String sValue = ci.nextArgument();
310 ci.println("Key not supplied");
313 if (sValue == null) {
314 ci.println("Value not supplied");
319 key = Integer.valueOf(sKey);
320 } catch (NumberFormatException nfe) {
321 ci.println("Key is not a valid integer: " + sKey);
324 c = (ConcurrentMap<Integer, StringContainer>) this.icluster.getCache(
325 containerName, cacheName);
327 ci.println("\nAdd mapping " + key + " = " + sValue);
328 c.put(key, new StringContainer(sValue));
330 ci.println("Cache " + cacheName + " on container " + containerName
335 public void _remove(CommandInterpreter ci) {
336 ConcurrentMap<Integer, StringContainer> c;
337 if (this.icluster == null) {
338 ci.println("\nNo Clustering services available");
341 String containerName = ci.nextArgument();
342 if (containerName == null) {
343 ci.println("containerName not supplied");
346 String cacheName = ci.nextArgument();
347 if (cacheName == null) {
348 ci.println("Cache not supplied");
351 String sKey = ci.nextArgument();
353 ci.println("Key not supplied");
358 key = Integer.valueOf(sKey);
359 } catch (NumberFormatException nfe) {
360 ci.println("Key is not a valid integer: " + sKey);
362 c = (ConcurrentMap<Integer, StringContainer>) this.icluster.getCache(
363 containerName, cacheName);
365 ci.println("\nDelete key " + key);
368 ci.println("Cache " + cacheName + " on container " + containerName
373 public void _dumper(CommandInterpreter ci) {
374 ConcurrentMap<Object, Object> c;
375 String containerName = ci.nextArgument();
376 if (containerName == null) {
377 ci.println("containerName not supplied");
380 String cacheName = ci.nextArgument();
381 if (cacheName == null) {
382 ci.println("Cache not supplied");
385 c = (ConcurrentMap<Object, Object>) this.icluster.getCache(containerName, cacheName);
387 for (Map.Entry<Object, Object> e : c.entrySet()) {
388 Map.Entry<Object, Object> entry = e;
389 Object v = entry.getValue();
390 String res = "<NOT KNOWN>";
394 ci.println("Element " + entry.getKey() + "(hashCode="
395 + entry.getKey().hashCode() + ") has value = (" + res
399 ci.println("Cache " + cacheName + " on container " + containerName
404 public void _get(CommandInterpreter ci) {
405 ConcurrentMap<Integer, StringContainer> c;
406 if (this.icluster == null) {
407 ci.println("\nNo Clustering services available");
410 String containerName = ci.nextArgument();
411 if (containerName == null) {
412 ci.println("containerName not supplied");
415 String cacheName = ci.nextArgument();
416 if (cacheName == null) {
417 ci.println("Cache not supplied");
420 String sKey = ci.nextArgument();
422 ci.println("Key not supplied");
427 key = Integer.valueOf(sKey);
428 } catch (NumberFormatException nfe) {
429 ci.println("Key is not a valid integer: " + sKey);
431 c = (ConcurrentMap<Integer, StringContainer>) this.icluster.getCache(
432 containerName, cacheName);
434 ci.println("\nGet key (" + key + ")=(" + c.get(key) + ")");
436 ci.println("Cache " + cacheName + " on container " + containerName
441 @SuppressWarnings("deprecation") //TODO: remove call to deprecated amIStandby
442 public void _getRole(CommandInterpreter ci) {
443 if (this.icluster == null) {
444 ci.println("\nNo Clustering services available");
447 String role = "Active";
448 if (this.icluster.amIStandby()) {
451 ci.println("My role is: " + role);
454 @SuppressWarnings("deprecation") //TODO: remove call to deprecated getActiveAddres
455 public void _getActive(CommandInterpreter ci) {
456 if (this.icluster == null) {
457 ci.println("\nNo Clustering services available");
460 ci.println("Current active address is "
461 + this.icluster.getActiveAddress());
464 @SuppressWarnings("deprecation") //TODO: remove use of deprecated listenRoleChange
465 public void _listenActive(CommandInterpreter ci) {
466 if (this.icluster == null) {
467 ci.println("\nNo Clustering services available");
470 this.doListen = new DoListenRoleChanged();
472 this.icluster.listenRoleChange(this.doListen);
473 } catch (ListenRoleChangeAddException e) {
474 ci.println("Exception while registering the listener");
477 ci.println("Register listenRoleChanges");
480 @SuppressWarnings("deprecation") //TODO: remove deprecated call to unlistenRoleChange
481 public void _unlistenActive(CommandInterpreter ci) {
482 if (this.icluster == null) {
483 ci.println("\nNo Clustering services available");
486 if (this.doListen != null) {
487 this.icluster.unlistenRoleChange(this.doListen);
488 ci.println("Unregistered Active notifications");
492 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("\tgetRole - Tell if active or standby\n");
640 help.append("\tgetActive - Report the IP address of Active\n");
642 .append("\tputComplex - Fill a more complex data structure\n");
644 .append("\tupdateComplex - Update the value of a more complex data structure\n");
646 .append("\tgetLogLevel - Get the loglevel for the logger specified\n");
648 .append("\tsetLogLevel - Set the loglevel for the logger specified\n");
649 return help.toString();