blob: 39d6c49ab03554b67a33a234a6c44cc044112d16 [file] [log] [blame]
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -07001package net.onrc.onos.datagrid;
2
3import java.io.FileNotFoundException;
4import java.util.ArrayList;
5import java.util.Collection;
6import java.util.HashMap;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -07007import java.util.LinkedList;
Jonathan Hart18ad55c2013-11-11 22:49:55 -08008import java.util.List;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -07009import java.util.Map;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070010import java.util.Set;
Jonathan Hart18ad55c2013-11-11 22:49:55 -080011import java.util.concurrent.TimeUnit;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070012
13import net.floodlightcontroller.core.IFloodlightProviderService;
14import net.floodlightcontroller.core.module.FloodlightModuleContext;
15import net.floodlightcontroller.core.module.FloodlightModuleException;
16import net.floodlightcontroller.core.module.IFloodlightModule;
17import net.floodlightcontroller.core.module.IFloodlightService;
Pavlin Radoslavovda7ef612013-10-30 16:12:14 -070018import net.floodlightcontroller.restserver.IRestApiService;
Pavlin Radoslavovda7ef612013-10-30 16:12:14 -070019import net.onrc.onos.datagrid.web.DatagridWebRoutable;
TeruU80ce5062014-03-03 17:16:13 -080020import net.onrc.onos.ofcontroller.devicemanager.IDeviceEventHandler;
21import net.onrc.onos.ofcontroller.devicemanager.OnosDevice;
Jonathan Hart7804bea2014-01-07 10:50:52 -080022import net.onrc.onos.ofcontroller.proxyarp.ArpReplyNotification;
23import net.onrc.onos.ofcontroller.proxyarp.IArpReplyEventHandler;
24import net.onrc.onos.ofcontroller.proxyarp.IPacketOutEventHandler;
25import net.onrc.onos.ofcontroller.proxyarp.PacketOutNotification;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070026import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
27
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070028import org.slf4j.Logger;
29import org.slf4j.LoggerFactory;
30
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -080031import com.esotericsoftware.kryo.Kryo;
32import com.esotericsoftware.kryo.io.Input;
33import com.esotericsoftware.kryo.io.Output;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070034import com.hazelcast.config.Config;
35import com.hazelcast.config.FileSystemXmlConfig;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070036import com.hazelcast.core.EntryEvent;
37import com.hazelcast.core.EntryListener;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070038import com.hazelcast.core.Hazelcast;
39import com.hazelcast.core.HazelcastInstance;
Toshio Koide3738ee52014-02-12 14:57:39 -080040import com.hazelcast.core.IList;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070041import com.hazelcast.core.IMap;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070042import com.hazelcast.instance.GroupProperties;
Toshio Koide3738ee52014-02-12 14:57:39 -080043import net.onrc.onos.intent.Intent;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070044
45/**
46 * A datagrid service that uses Hazelcast as a datagrid.
47 * The relevant data is stored in the Hazelcast datagrid and shared as
48 * appropriate in a multi-node cluster.
49 */
50public class HazelcastDatagrid implements IFloodlightModule, IDatagridService {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070051 private static final int MAX_BUFFER_SIZE = 64 * 1024;
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070052
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070053 static final Logger log = LoggerFactory.getLogger(HazelcastDatagrid.class);
54 private IRestApiService restApi;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070055
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070056 static final String HAZELCAST_CONFIG_FILE = "datagridConfig";
57 private HazelcastInstance hazelcastInstance;
58 private Config hazelcastConfig;
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -070059
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070060 private final KryoFactory kryoFactory = new KryoFactory();
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070061
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070062 private final Map<String, IEventChannel<?, ?>> eventChannels = new HashMap<>();
Pavlin Radoslavov7940b652014-02-13 19:42:05 -080063
Jonathan Hart7804bea2014-01-07 10:50:52 -080064 // State related to the packet out map
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070065 private static final String PACKET_OUT_MAP_NAME = "packetOutMap";
66 private IMap<PacketOutNotification, byte[]> packetOutMap;
67 private final List<IPacketOutEventHandler> packetOutEventHandlers = new ArrayList<>();
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -080068
Jonathan Hart18ad55c2013-11-11 22:49:55 -080069 private final byte[] dummyByte = {0};
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -070070
Jonathan Hart7804bea2014-01-07 10:50:52 -080071 // State related to the ARP reply map
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070072 private static final String ARP_REPLY_MAP_NAME = "arpReplyMap";
73 private IMap<ArpReplyNotification, byte[]> arpReplyMap;
74 private final List<IArpReplyEventHandler> arpReplyEventHandlers = new ArrayList<>();
75
76
77 private static final String INTENT_LIST_NAME = "intentList";
78 private IList<Intent> intentList;
Toshio Koide3738ee52014-02-12 14:57:39 -080079
80 @Override
81 public void registerIntent(Collection<Intent> intents) {
82 intentList.addAll(intents);
83 }
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070084
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070085
TeruU80ce5062014-03-03 17:16:13 -080086 // State related to the Network Device map
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070087 private static final String MAP_DEVICE_NAME = "mapDevice";
88 private IMap<Long, OnosDevice> mapDevice;
89 private final List<IDeviceEventHandler> deviceEventHandlers = new ArrayList<>();
90
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070091 /**
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070092 * MapDeviceListener - reacts to Device related events.
93 */
TeruU80ce5062014-03-03 17:16:13 -080094 class MapDeviceListener implements EntryListener<Long, OnosDevice> {
95
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070096 @Override
97 public void entryAdded(EntryEvent<Long, OnosDevice> event) {
98 for (IDeviceEventHandler deviceEventHandler : deviceEventHandlers) {
99 deviceEventHandler.addDeviceEvent(event.getKey(), event.getValue());
100 }
101 }
102
103 @Override
104 public void entryRemoved(EntryEvent<Long, OnosDevice> event) {
105 for (IDeviceEventHandler deviceEventHandler : deviceEventHandlers) {
106 deviceEventHandler.deleteDeviceEvent(event.getKey(), event.getValue());
107 }
108 }
109
110 @Override
111 public void entryUpdated(EntryEvent<Long, OnosDevice> event) {
112 for (IDeviceEventHandler deviceEventHandler : deviceEventHandlers) {
113 deviceEventHandler.updateDeviceEvent(event.getKey(), event.getValue());
114 }
115 }
116
117 @Override
118 public void entryEvicted(EntryEvent<Long, OnosDevice> arg0) {
119 //Not used.
120 }
TeruU80ce5062014-03-03 17:16:13 -0800121 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800122
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800123 /**
Jonathan Hart7804bea2014-01-07 10:50:52 -0800124 * Class for receiving notifications for sending packet-outs.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700125 * <p/>
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800126 * The datagrid map is:
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700127 * - Key: Packet-out to send (PacketOutNotification)
128 * - Value: dummy value (we only need the key) (byte[])
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800129 */
Jonathan Hart7804bea2014-01-07 10:50:52 -0800130 class PacketOutMapListener implements EntryListener<PacketOutNotification, byte[]> {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700131 /**
132 * Receive a notification that an entry is added.
133 *
134 * @param event the notification event for the entry.
135 */
136 @Override
137 public void entryAdded(EntryEvent<PacketOutNotification, byte[]> event) {
138 for (IPacketOutEventHandler packetOutEventHandler : packetOutEventHandlers) {
139 packetOutEventHandler.packetOutNotification(event.getKey());
140 }
141 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800142
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700143 /**
144 * Receive a notification that an entry is removed.
145 *
146 * @param event the notification event for the entry.
147 */
148 @Override
149 public void entryRemoved(EntryEvent<PacketOutNotification, byte[]> event) {
150 // Not used
151 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800152
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700153 /**
154 * Receive a notification that an entry is updated.
155 *
156 * @param event the notification event for the entry.
157 */
158 @Override
159 public void entryUpdated(EntryEvent<PacketOutNotification, byte[]> event) {
160 // Not used
161 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800162
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700163 /**
164 * Receive a notification that an entry is evicted.
165 *
166 * @param event the notification event for the entry.
167 */
168 @Override
169 public void entryEvicted(EntryEvent<PacketOutNotification, byte[]> event) {
170 // Not used
171 }
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800172 }
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700173
174 /**
Jonathan Hart7804bea2014-01-07 10:50:52 -0800175 * Class for receiving notifications for sending packet-outs.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700176 * <p/>
Jonathan Hart7804bea2014-01-07 10:50:52 -0800177 * The datagrid map is:
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700178 * - Key: Packet-out to send (PacketOutNotification)
179 * - Value: dummy value (we only need the key) (byte[])
Jonathan Hart7804bea2014-01-07 10:50:52 -0800180 */
181 class ArpReplyMapListener implements EntryListener<ArpReplyNotification, byte[]> {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700182 /**
183 * Receive a notification that an entry is added.
184 *
185 * @param event the notification event for the entry.
186 */
187 @Override
188 public void entryAdded(EntryEvent<ArpReplyNotification, byte[]> event) {
189 triggerEventHandler(event.getKey());
190 }
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800191
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700192 @Override
193 public void entryUpdated(EntryEvent<ArpReplyNotification, byte[]> event) {
194 triggerEventHandler(event.getKey());
195 }
196
197 @Override
198 public void entryRemoved(EntryEvent<ArpReplyNotification, byte[]> event) {
199 // Not used for ARP replies
200 }
201
202 @Override
203 public void entryEvicted(EntryEvent<ArpReplyNotification, byte[]> event) {
204 // Not used for ARP replies
205 }
206
207 /**
208 * Handle an event.
209 * @param notification notification
210 */
211 private void triggerEventHandler(ArpReplyNotification notification) {
212 for (IArpReplyEventHandler arpReplyEventHandler : arpReplyEventHandlers) {
213 arpReplyEventHandler.arpReplyEvent(notification);
214 }
215 }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800216 }
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700217
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700218 /**
219 * Initialize the Hazelcast Datagrid operation.
220 *
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700221 * @param configFilename the configuration filename.
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700222 */
223 public void init(String configFilename) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700224 /*
225 System.setProperty("hazelcast.socket.receive.buffer.size", "32");
226 System.setProperty("hazelcast.socket.send.buffer.size", "32");
227 */
228 // System.setProperty("hazelcast.heartbeat.interval.seconds", "100");
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800229
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700230 // Init from configuration file
231 try {
232 hazelcastConfig = new FileSystemXmlConfig(configFilename);
233 } catch (FileNotFoundException e) {
234 log.error("Error opening Hazelcast XML configuration. File not found: " + configFilename, e);
235 }
236 /*
237 hazelcastConfig.setProperty(GroupProperties.PROP_IO_THREAD_COUNT, "1");
238 hazelcastConfig.setProperty(GroupProperties.PROP_OPERATION_THREAD_COUNT, "1");
239 hazelcastConfig.setProperty(GroupProperties.PROP_EVENT_THREAD_COUNT, "1");
240 */
241 //
242 hazelcastConfig.setProperty(GroupProperties.PROP_EVENT_QUEUE_CAPACITY, "4000000");
243 hazelcastConfig.setProperty(GroupProperties.PROP_SOCKET_RECEIVE_BUFFER_SIZE, "4096");
244 hazelcastConfig.setProperty(GroupProperties.PROP_SOCKET_SEND_BUFFER_SIZE, "4096");
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700245 }
246
247 /**
248 * Shutdown the Hazelcast Datagrid operation.
249 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800250 @Override
251 protected void finalize() {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700252 close();
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700253 }
254
255 /**
256 * Shutdown the Hazelcast Datagrid operation.
257 */
258 public void close() {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700259 Hazelcast.shutdownAll();
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700260 }
261
262 /**
263 * Get the collection of offered module services.
264 *
265 * @return the collection of offered module services.
266 */
267 @Override
268 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800269 Collection<Class<? extends IFloodlightService>> l =
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700270 new ArrayList<Class<? extends IFloodlightService>>();
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700271 l.add(IDatagridService.class);
272 return l;
273 }
274
275 /**
276 * Get the collection of implemented services.
277 *
278 * @return the collection of implemented services.
279 */
280 @Override
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800281 public Map<Class<? extends IFloodlightService>, IFloodlightService>
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700282 getServiceImpls() {
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700283 Map<Class<? extends IFloodlightService>,
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700284 IFloodlightService> m =
285 new HashMap<Class<? extends IFloodlightService>,
286 IFloodlightService>();
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700287 m.put(IDatagridService.class, this);
288 return m;
289 }
290
291 /**
292 * Get the collection of modules this module depends on.
293 *
294 * @return the collection of modules this module depends on.
295 */
296 @Override
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800297 public Collection<Class<? extends IFloodlightService>>
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700298 getModuleDependencies() {
299 Collection<Class<? extends IFloodlightService>> l =
300 new ArrayList<Class<? extends IFloodlightService>>();
301 l.add(IFloodlightProviderService.class);
302 l.add(IRestApiService.class);
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700303 return l;
304 }
305
306 /**
307 * Initialize the module.
308 *
309 * @param context the module context to use for the initialization.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700310 * @throws FloodlightModuleException on error
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700311 */
312 @Override
313 public void init(FloodlightModuleContext context)
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700314 throws FloodlightModuleException {
315 restApi = context.getServiceImpl(IRestApiService.class);
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700316
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700317 // Get the configuration file name and configure the Datagrid
318 Map<String, String> configMap = context.getConfigParams(this);
319 String configFilename = configMap.get(HAZELCAST_CONFIG_FILE);
320 this.init(configFilename);
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700321 }
322
323 /**
324 * Startup module operation.
325 *
326 * @param context the module context to use for the startup.
327 */
328 @Override
329 public void startUp(FloodlightModuleContext context) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700330 hazelcastInstance = Hazelcast.newHazelcastInstance(hazelcastConfig);
Pavlin Radoslavovda7ef612013-10-30 16:12:14 -0700331
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700332 restApi.addRestletRoutable(new DatagridWebRoutable());
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800333
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700334 packetOutMap = hazelcastInstance.getMap(PACKET_OUT_MAP_NAME);
335 packetOutMap.addEntryListener(new PacketOutMapListener(), true);
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800336
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700337 arpReplyMap = hazelcastInstance.getMap(ARP_REPLY_MAP_NAME);
338 arpReplyMap.addEntryListener(new ArpReplyMapListener(), true);
339 intentList = hazelcastInstance.getList(INTENT_LIST_NAME);
340
341 mapDevice = hazelcastInstance.getMap(MAP_DEVICE_NAME);
342 mapDevice.addEntryListener(new MapDeviceListener(), true);
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700343 }
344
345 /**
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800346 * Create an event channel.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700347 * <p/>
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800348 * If the channel already exists, just return it.
349 * NOTE: The channel is started automatically.
350 *
351 * @param channelName the event channel name.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700352 * @param <K> the type of the Key in the Key-Value store.
353 * @param <V> the type of the Value in the Key-Value store.
354 * @param typeK the type of the Key in the Key-Value store.
355 * @param typeV the type of the Value in the Key-Value store.
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800356 * @return the event channel for the channel name.
357 */
358 @Override
359 public <K, V> IEventChannel<K, V> createChannel(String channelName,
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700360 Class<K> typeK, Class<V> typeV) {
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700361 synchronized (eventChannels) {
362 IEventChannel<K, V> eventChannel =
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700363 createChannelImpl(channelName, typeK, typeV);
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700364 eventChannel.startup();
365 return eventChannel;
366 }
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800367 }
368
369 /**
370 * Create an event channel implementation.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700371 * <p/>
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800372 * If the channel already exists, just return it.
373 * NOTE: The caller must call IEventChannel.startup() to startup the
374 * channel operation.
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700375 * NOTE: The caller must own the lock on "eventChannels".
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800376 *
377 * @param channelName the event channel name.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700378 * @param <K> the type of the Key in the Key-Value store.
379 * @param <V> the type of the Value in the Key-Value store.
380 * @param typeK the type of the Key in the Key-Value store.
381 * @param typeV the type of the Value in the Key-Value store.
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800382 * @return the event channel for the channel name.
383 */
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700384 private <K, V> IEventChannel<K, V> createChannelImpl(
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700385 String channelName,
386 Class<K> typeK, Class<V> typeV) {
387 IEventChannel<K, V> castedEventChannel;
388 IEventChannel<?, ?> genericEventChannel =
389 eventChannels.get(channelName);
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800390
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700391 // Add the channel if the first listener
392 if (genericEventChannel == null) {
393 castedEventChannel =
394 new HazelcastEventChannel<K, V>(hazelcastInstance,
395 channelName, typeK, typeV);
396 eventChannels.put(channelName, castedEventChannel);
397 } else {
398 //
399 // TODO: Find if we can use Java internal support to check for
400 // type mismatch.
401 //
402 if (!genericEventChannel.verifyKeyValueTypes(typeK, typeV)) {
403 throw new ClassCastException("Key-value type mismatch for event channel " + channelName);
404 }
405 castedEventChannel = (IEventChannel<K, V>) genericEventChannel;
406 }
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800407
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700408 return castedEventChannel;
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800409 }
410
411 /**
412 * Add event channel listener.
413 *
414 * NOTE: The channel is started automatically right after the listener
415 * is added.
416 *
417 * @param channelName the event channel name.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700418 * @param listener the listener to add.
419 * @param <K> the type of the Key in the Key-Value store.
420 * @param <V> the type of the Value in the Key-Value store.
421 * @param typeK the type of the Key in the Key-Value store.
422 * @param typeV the type of the Value in the Key-Value store.
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800423 * @return the event channel for the channel name.
424 */
425 @Override
426 public <K, V> IEventChannel<K, V> addListener(String channelName,
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700427 IEventChannelListener<K, V> listener,
428 Class<K> typeK, Class<V> typeV) {
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700429 synchronized (eventChannels) {
430 IEventChannel<K, V> eventChannel =
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700431 createChannelImpl(channelName, typeK, typeV);
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700432 eventChannel.addListener(listener);
433 eventChannel.startup();
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800434
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700435 return eventChannel;
436 }
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800437 }
438
439 /**
440 * Remove event channel listener.
441 *
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700442 * @param <K> the type of the Key in the Key-Value store.
443 * @param <V> the type of the Value in the Key-Value store.
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800444 * @param channelName the event channel name.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700445 * @param listener the listener to remove.
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800446 */
447 @Override
448 public <K, V> void removeListener(String channelName,
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700449 IEventChannelListener<K, V> listener) {
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700450 synchronized (eventChannels) {
451 IEventChannel<?, ?> genericEventChannel =
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700452 eventChannels.get(channelName);
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800453
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700454 if (genericEventChannel != null) {
455 //
456 // TODO: Find if we can use Java internal support to check for
457 // type mismatch.
458 // NOTE: Using "ClassCastException" exception below doesn't
459 // work.
460 //
461 IEventChannel<K, V> castedEventChannel =
462 (IEventChannel<K, V>) genericEventChannel;
463 castedEventChannel.removeListener(listener);
464 }
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700465 }
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800466 }
467
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800468 @Override
Jonathan Hartc6325622014-01-14 16:37:50 -0800469 public void registerPacketOutEventHandler(IPacketOutEventHandler packetOutEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700470 if (packetOutEventHandler != null) {
471 packetOutEventHandlers.add(packetOutEventHandler);
472 }
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800473 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800474
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800475 @Override
Jonathan Hartc6325622014-01-14 16:37:50 -0800476 public void deregisterPacketOutEventHandler(IPacketOutEventHandler packetOutEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700477 packetOutEventHandlers.remove(packetOutEventHandler);
Jonathan Hart7804bea2014-01-07 10:50:52 -0800478 }
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800479
Jonathan Hart7804bea2014-01-07 10:50:52 -0800480 @Override
481 public void registerArpReplyEventHandler(IArpReplyEventHandler arpReplyEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700482 if (arpReplyEventHandler != null) {
483 arpReplyEventHandlers.add(arpReplyEventHandler);
484 }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800485 }
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800486
Jonathan Hart7804bea2014-01-07 10:50:52 -0800487 @Override
488 public void deregisterArpReplyEventHandler(IArpReplyEventHandler arpReplyEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700489 arpReplyEventHandlers.remove(arpReplyEventHandler);
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800490 }
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700491
TeruU80ce5062014-03-03 17:16:13 -0800492 @Override
493 public void registerMapDeviceEventHandler(IDeviceEventHandler deviceEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700494 if (deviceEventHandler != null) {
495 deviceEventHandlers.add(deviceEventHandler);
496 }
TeruU80ce5062014-03-03 17:16:13 -0800497 }
498
499 @Override
500 public void deregisterMapDeviceEventHandler(IDeviceEventHandler deviceEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700501 deviceEventHandlers.remove(deviceEventHandler);
TeruU80ce5062014-03-03 17:16:13 -0800502 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800503
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800504 @Override
Jonathan Hart7804bea2014-01-07 10:50:52 -0800505 public void sendPacketOutNotification(PacketOutNotification packetOutNotification) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700506 packetOutMap.putAsync(packetOutNotification, dummyByte, 1L, TimeUnit.MILLISECONDS);
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800507 }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800508
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700509 @Override
510 public void sendArpReplyNotification(ArpReplyNotification arpReply) {
511 arpReplyMap.putAsync(arpReply, dummyByte, 1L, TimeUnit.MILLISECONDS);
512 }
513
514 @Override
515 public void sendNotificationDeviceAdded(Long mac, OnosDevice dev) {
516 log.debug("DeviceAdded in datagrid. mac {}", dev.getMacAddress());
517 mapDevice.putAsync(mac, dev);
518 }
519
520 @Override
521 public void sendNotificationDeviceDeleted(OnosDevice dev) {
522 long mac = dev.getMacAddress().toLong();
523 if (mapDevice.containsKey(mac)) {
524 log.debug("DeviceDeleted in datagrid. mac {}", dev.getMacAddress());
525 mapDevice.removeAsync(mac);
526 }
527 }
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700528}