1 package org.opendaylight.controller.ping.service.impl;
3 import java.util.HashMap;
5 import java.util.concurrent.ExecutionException;
6 import java.util.concurrent.Future;
8 import org.opendaylight.controller.ping.service.api.PingServiceAPI;
9 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareConsumer;
10 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
11 import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
12 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.ping.rev130911.PingService;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.ping.rev130911.SendEchoInputBuilder;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.ping.rev130911.SendEchoOutput;
16 import org.opendaylight.yangtools.yang.common.RpcResult;
17 import org.osgi.framework.BundleActivator;
18 import org.osgi.framework.BundleContext;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
22 public class PingServiceImpl extends AbstractBindingAwareConsumer implements
23 BundleActivator, BindingAwareConsumer, PingServiceAPI {
24 private static Logger log = LoggerFactory.getLogger(PingServiceImpl.class);
26 private PingService pingService;
27 private ConsumerContext session;
28 private Map<Ipv4Address, Future<RpcResult<SendEchoOutput>>> asyncPingEntryMap;
31 public void onSessionInitialized(ConsumerContext session) {
32 this.session = session;
33 this.pingService = this.session.getRpcService(PingService.class);
37 protected void startImpl(BundleContext context) {
38 asyncPingEntryMap = new HashMap<>();
39 context.registerService(PingServiceAPI.class, this, null);
43 protected void stopImpl(BundleContext context) {
44 asyncPingEntryMap.clear();
48 public PingResult pingDestinationSync(String address) {
49 return _pingDestinationSync(address);
53 public PingResult pingDestinationAsync(String address) {
54 return _pingDestinationAsync(address);
58 public void pingAsyncClear(String address) {
59 _pingAsyncClear(address);
62 private PingResult _pingDestinationSync(String address) {
63 if (pingService == null) { return PingResult.Error; } // No pingService service found.
66 Ipv4Address destination = new Ipv4Address(address);
67 SendEchoInputBuilder ib = new SendEchoInputBuilder();
68 ib.setDestination(destination);
69 return mapResult(pingService.sendEcho(ib.build()).get().getResult().getEchoResult());
70 } catch (InterruptedException ie) {
71 log.warn("InterruptedException received by pingDestinationSync: {} from: {}",
72 address, ie.getMessage());
73 } catch (ExecutionException ee) {
74 log.warn("ExecutionException received by pingDestinationSync: {} from: {}",
75 address, ee.getMessage());
77 return PingResult.Error;
80 private synchronized PingResult _pingDestinationAsync(String address) {
81 if (pingService == null) { return PingResult.Error; } // No pingService service found.
83 /** Look for destination in asyncPingEntryMap. If none is found, create a new entry
84 * and return "in progress". This will happen on the very first time async is requested.
86 * NOTE: In a real scenario, you would want to consider a cache which automatically drops
87 * entries, so implementation does not need to rely on users calling async clear to remove
88 * the entries from the map. An example for doing such would be Google's caches or a
89 * weakhash map; which we deliberately chose not to use here for sake of simplicity.
91 final Ipv4Address destination = new Ipv4Address(address);
92 final Future<RpcResult<SendEchoOutput>> rpcResultFuture = asyncPingEntryMap.get(destination);
93 if (rpcResultFuture == null) {
94 SendEchoInputBuilder ib = new SendEchoInputBuilder();
95 ib.setDestination(destination);
96 asyncPingEntryMap.put(destination, pingService.sendEcho(ib.build()));
97 log.info("Starting pingDestinationAsync: {}", address);
98 return PingResult.InProgress;
101 /** Pending result may not be ready to be consumed. In such case, use "in progress".
103 if (!rpcResultFuture.isDone()) {
104 log.info("pingDestinationAsync: {} get result is not ready (ie. inProgress)", address);
105 return PingResult.InProgress;
108 /** If we made it this far, we know that rpcResultFuture is ready for consumption.
111 PingResult pingResult = mapResult(rpcResultFuture.get().getResult().getEchoResult());
112 log.info("pingDestinationAsync: {} get result is {}", address, pingResult);
114 } catch (InterruptedException ie) {
115 log.warn("InterruptedException received by pingDestinationAsync: {} from: {}",
116 address, ie.getMessage());
117 } catch (ExecutionException ee) {
118 log.warn("ExecutionException received by pingDestinationAsync: {} from: {}",
119 address, ee.getMessage());
121 return PingResult.Error;
124 private synchronized void _pingAsyncClear(String address) {
125 asyncPingEntryMap.remove(new Ipv4Address(address));
126 log.info("Removing pingDestinationAsync: {}", address);
129 private static PingResult mapResult(SendEchoOutput.EchoResult echoResult) {
130 // Translate echoResult to pingResult
131 switch (echoResult) {
133 return PingResult.GotResponse;
135 return PingResult.NoResponse;
140 return PingResult.Error;