blob: 9bd838be026eba7f45d413753adf913d069d8c38 [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
Pavlin Radoslavov07af5f22014-03-21 15:17:58 -070062 //
63 // NOTE: eventChannels is kept thread safe by using explicit "synchronized"
64 // blocks below. Those are needed to protect the integrity of each entry
65 // instance, and avoid preemption during channel creation/startup.
66 //
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070067 private final Map<String, IEventChannel<?, ?>> eventChannels = new HashMap<>();
Pavlin Radoslavov7940b652014-02-13 19:42:05 -080068
Jonathan Hart7804bea2014-01-07 10:50:52 -080069 // State related to the packet out map
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070070 private static final String PACKET_OUT_MAP_NAME = "packetOutMap";
71 private IMap<PacketOutNotification, byte[]> packetOutMap;
72 private final List<IPacketOutEventHandler> packetOutEventHandlers = new ArrayList<>();
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -080073
Jonathan Hart18ad55c2013-11-11 22:49:55 -080074 private final byte[] dummyByte = {0};
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -070075
Jonathan Hart7804bea2014-01-07 10:50:52 -080076 // State related to the ARP reply map
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070077 private static final String ARP_REPLY_MAP_NAME = "arpReplyMap";
78 private IMap<ArpReplyNotification, byte[]> arpReplyMap;
79 private final List<IArpReplyEventHandler> arpReplyEventHandlers = new ArrayList<>();
80
81
82 private static final String INTENT_LIST_NAME = "intentList";
83 private IList<Intent> intentList;
Toshio Koide3738ee52014-02-12 14:57:39 -080084
85 @Override
86 public void registerIntent(Collection<Intent> intents) {
87 intentList.addAll(intents);
88 }
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070089
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070090
TeruU80ce5062014-03-03 17:16:13 -080091 // State related to the Network Device map
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070092 private static final String MAP_DEVICE_NAME = "mapDevice";
93 private IMap<Long, OnosDevice> mapDevice;
94 private final List<IDeviceEventHandler> deviceEventHandlers = new ArrayList<>();
95
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -070096 /**
Ray Milkey0ab2d8a2014-03-20 14:30:10 -070097 * MapDeviceListener - reacts to Device related events.
98 */
TeruU80ce5062014-03-03 17:16:13 -080099 class MapDeviceListener implements EntryListener<Long, OnosDevice> {
100
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700101 @Override
102 public void entryAdded(EntryEvent<Long, OnosDevice> event) {
103 for (IDeviceEventHandler deviceEventHandler : deviceEventHandlers) {
104 deviceEventHandler.addDeviceEvent(event.getKey(), event.getValue());
105 }
106 }
107
108 @Override
109 public void entryRemoved(EntryEvent<Long, OnosDevice> event) {
110 for (IDeviceEventHandler deviceEventHandler : deviceEventHandlers) {
111 deviceEventHandler.deleteDeviceEvent(event.getKey(), event.getValue());
112 }
113 }
114
115 @Override
116 public void entryUpdated(EntryEvent<Long, OnosDevice> event) {
117 for (IDeviceEventHandler deviceEventHandler : deviceEventHandlers) {
118 deviceEventHandler.updateDeviceEvent(event.getKey(), event.getValue());
119 }
120 }
121
122 @Override
123 public void entryEvicted(EntryEvent<Long, OnosDevice> arg0) {
124 //Not used.
125 }
TeruU80ce5062014-03-03 17:16:13 -0800126 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800127
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800128 /**
Jonathan Hart7804bea2014-01-07 10:50:52 -0800129 * Class for receiving notifications for sending packet-outs.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700130 * <p/>
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800131 * The datagrid map is:
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700132 * - Key: Packet-out to send (PacketOutNotification)
133 * - Value: dummy value (we only need the key) (byte[])
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800134 */
Jonathan Hart7804bea2014-01-07 10:50:52 -0800135 class PacketOutMapListener implements EntryListener<PacketOutNotification, byte[]> {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700136 /**
137 * Receive a notification that an entry is added.
138 *
139 * @param event the notification event for the entry.
140 */
141 @Override
142 public void entryAdded(EntryEvent<PacketOutNotification, byte[]> event) {
143 for (IPacketOutEventHandler packetOutEventHandler : packetOutEventHandlers) {
144 packetOutEventHandler.packetOutNotification(event.getKey());
145 }
146 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800147
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700148 /**
149 * Receive a notification that an entry is removed.
150 *
151 * @param event the notification event for the entry.
152 */
153 @Override
154 public void entryRemoved(EntryEvent<PacketOutNotification, byte[]> event) {
155 // Not used
156 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800157
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700158 /**
159 * Receive a notification that an entry is updated.
160 *
161 * @param event the notification event for the entry.
162 */
163 @Override
164 public void entryUpdated(EntryEvent<PacketOutNotification, byte[]> event) {
165 // Not used
166 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800167
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700168 /**
169 * Receive a notification that an entry is evicted.
170 *
171 * @param event the notification event for the entry.
172 */
173 @Override
174 public void entryEvicted(EntryEvent<PacketOutNotification, byte[]> event) {
175 // Not used
176 }
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800177 }
Pavlin Radoslavovaaace7f2013-10-25 19:42:00 -0700178
179 /**
Jonathan Hart7804bea2014-01-07 10:50:52 -0800180 * Class for receiving notifications for sending packet-outs.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700181 * <p/>
Jonathan Hart7804bea2014-01-07 10:50:52 -0800182 * The datagrid map is:
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700183 * - Key: Packet-out to send (PacketOutNotification)
184 * - Value: dummy value (we only need the key) (byte[])
Jonathan Hart7804bea2014-01-07 10:50:52 -0800185 */
186 class ArpReplyMapListener implements EntryListener<ArpReplyNotification, byte[]> {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700187 /**
188 * Receive a notification that an entry is added.
189 *
190 * @param event the notification event for the entry.
191 */
192 @Override
193 public void entryAdded(EntryEvent<ArpReplyNotification, byte[]> event) {
194 triggerEventHandler(event.getKey());
195 }
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800196
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700197 @Override
198 public void entryUpdated(EntryEvent<ArpReplyNotification, byte[]> event) {
199 triggerEventHandler(event.getKey());
200 }
201
202 @Override
203 public void entryRemoved(EntryEvent<ArpReplyNotification, byte[]> event) {
204 // Not used for ARP replies
205 }
206
207 @Override
208 public void entryEvicted(EntryEvent<ArpReplyNotification, byte[]> event) {
209 // Not used for ARP replies
210 }
211
212 /**
213 * Handle an event.
214 * @param notification notification
215 */
216 private void triggerEventHandler(ArpReplyNotification notification) {
217 for (IArpReplyEventHandler arpReplyEventHandler : arpReplyEventHandlers) {
218 arpReplyEventHandler.arpReplyEvent(notification);
219 }
220 }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800221 }
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700222
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700223 /**
224 * Initialize the Hazelcast Datagrid operation.
225 *
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700226 * @param configFilename the configuration filename.
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700227 */
228 public void init(String configFilename) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700229 /*
230 System.setProperty("hazelcast.socket.receive.buffer.size", "32");
231 System.setProperty("hazelcast.socket.send.buffer.size", "32");
232 */
233 // System.setProperty("hazelcast.heartbeat.interval.seconds", "100");
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800234
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700235 // Init from configuration file
236 try {
237 hazelcastConfig = new FileSystemXmlConfig(configFilename);
238 } catch (FileNotFoundException e) {
239 log.error("Error opening Hazelcast XML configuration. File not found: " + configFilename, e);
240 }
241 /*
242 hazelcastConfig.setProperty(GroupProperties.PROP_IO_THREAD_COUNT, "1");
243 hazelcastConfig.setProperty(GroupProperties.PROP_OPERATION_THREAD_COUNT, "1");
244 hazelcastConfig.setProperty(GroupProperties.PROP_EVENT_THREAD_COUNT, "1");
245 */
246 //
247 hazelcastConfig.setProperty(GroupProperties.PROP_EVENT_QUEUE_CAPACITY, "4000000");
248 hazelcastConfig.setProperty(GroupProperties.PROP_SOCKET_RECEIVE_BUFFER_SIZE, "4096");
249 hazelcastConfig.setProperty(GroupProperties.PROP_SOCKET_SEND_BUFFER_SIZE, "4096");
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700250 }
251
252 /**
253 * Shutdown the Hazelcast Datagrid operation.
254 */
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800255 @Override
256 protected void finalize() {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700257 close();
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700258 }
259
260 /**
261 * Shutdown the Hazelcast Datagrid operation.
262 */
263 public void close() {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700264 Hazelcast.shutdownAll();
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700265 }
266
267 /**
268 * Get the collection of offered module services.
269 *
270 * @return the collection of offered module services.
271 */
272 @Override
273 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800274 Collection<Class<? extends IFloodlightService>> l =
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700275 new ArrayList<Class<? extends IFloodlightService>>();
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700276 l.add(IDatagridService.class);
277 return l;
278 }
279
280 /**
281 * Get the collection of implemented services.
282 *
283 * @return the collection of implemented services.
284 */
285 @Override
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800286 public Map<Class<? extends IFloodlightService>, IFloodlightService>
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700287 getServiceImpls() {
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700288 Map<Class<? extends IFloodlightService>,
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700289 IFloodlightService> m =
290 new HashMap<Class<? extends IFloodlightService>,
291 IFloodlightService>();
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700292 m.put(IDatagridService.class, this);
293 return m;
294 }
295
296 /**
297 * Get the collection of modules this module depends on.
298 *
299 * @return the collection of modules this module depends on.
300 */
301 @Override
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800302 public Collection<Class<? extends IFloodlightService>>
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700303 getModuleDependencies() {
304 Collection<Class<? extends IFloodlightService>> l =
305 new ArrayList<Class<? extends IFloodlightService>>();
306 l.add(IFloodlightProviderService.class);
307 l.add(IRestApiService.class);
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700308 return l;
309 }
310
311 /**
312 * Initialize the module.
313 *
314 * @param context the module context to use for the initialization.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700315 * @throws FloodlightModuleException on error
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700316 */
317 @Override
318 public void init(FloodlightModuleContext context)
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700319 throws FloodlightModuleException {
320 restApi = context.getServiceImpl(IRestApiService.class);
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700321
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700322 // Get the configuration file name and configure the Datagrid
323 Map<String, String> configMap = context.getConfigParams(this);
324 String configFilename = configMap.get(HAZELCAST_CONFIG_FILE);
325 this.init(configFilename);
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700326 }
327
328 /**
329 * Startup module operation.
330 *
331 * @param context the module context to use for the startup.
332 */
333 @Override
334 public void startUp(FloodlightModuleContext context) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700335 hazelcastInstance = Hazelcast.newHazelcastInstance(hazelcastConfig);
Pavlin Radoslavovda7ef612013-10-30 16:12:14 -0700336
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700337 restApi.addRestletRoutable(new DatagridWebRoutable());
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800338
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700339 packetOutMap = hazelcastInstance.getMap(PACKET_OUT_MAP_NAME);
340 packetOutMap.addEntryListener(new PacketOutMapListener(), true);
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800341
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700342 arpReplyMap = hazelcastInstance.getMap(ARP_REPLY_MAP_NAME);
343 arpReplyMap.addEntryListener(new ArpReplyMapListener(), true);
344 intentList = hazelcastInstance.getList(INTENT_LIST_NAME);
345
346 mapDevice = hazelcastInstance.getMap(MAP_DEVICE_NAME);
347 mapDevice.addEntryListener(new MapDeviceListener(), true);
Pavlin Radoslavov1308dc62013-10-25 15:54:31 -0700348 }
349
350 /**
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800351 * Create an event channel.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700352 * <p/>
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800353 * If the channel already exists, just return it.
354 * NOTE: The channel is started automatically.
355 *
356 * @param channelName the event channel name.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700357 * @param <K> the type of the Key in the Key-Value store.
358 * @param <V> the type of the Value in the Key-Value store.
359 * @param typeK the type of the Key in the Key-Value store.
360 * @param typeV the type of the Value in the Key-Value store.
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800361 * @return the event channel for the channel name.
362 */
363 @Override
364 public <K, V> IEventChannel<K, V> createChannel(String channelName,
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700365 Class<K> typeK, Class<V> typeV) {
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700366 synchronized (eventChannels) {
367 IEventChannel<K, V> eventChannel =
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700368 createChannelImpl(channelName, typeK, typeV);
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700369 eventChannel.startup();
370 return eventChannel;
371 }
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800372 }
373
374 /**
375 * Create an event channel implementation.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700376 * <p/>
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800377 * If the channel already exists, just return it.
378 * NOTE: The caller must call IEventChannel.startup() to startup the
379 * channel operation.
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700380 * NOTE: The caller must own the lock on "eventChannels".
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800381 *
382 * @param channelName the event channel name.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700383 * @param <K> the type of the Key in the Key-Value store.
384 * @param <V> the type of the Value in the Key-Value store.
385 * @param typeK the type of the Key in the Key-Value store.
386 * @param typeV the type of the Value in the Key-Value store.
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800387 * @return the event channel for the channel name.
388 */
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700389 private <K, V> IEventChannel<K, V> createChannelImpl(
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700390 String channelName,
391 Class<K> typeK, Class<V> typeV) {
392 IEventChannel<K, V> castedEventChannel;
393 IEventChannel<?, ?> genericEventChannel =
394 eventChannels.get(channelName);
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800395
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700396 // Add the channel if the first listener
397 if (genericEventChannel == null) {
398 castedEventChannel =
399 new HazelcastEventChannel<K, V>(hazelcastInstance,
400 channelName, typeK, typeV);
401 eventChannels.put(channelName, castedEventChannel);
402 } else {
403 //
404 // TODO: Find if we can use Java internal support to check for
405 // type mismatch.
406 //
407 if (!genericEventChannel.verifyKeyValueTypes(typeK, typeV)) {
408 throw new ClassCastException("Key-value type mismatch for event channel " + channelName);
409 }
410 castedEventChannel = (IEventChannel<K, V>) genericEventChannel;
411 }
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800412
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700413 return castedEventChannel;
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800414 }
415
416 /**
417 * Add event channel listener.
418 *
419 * NOTE: The channel is started automatically right after the listener
420 * is added.
421 *
422 * @param channelName the event channel name.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700423 * @param listener the listener to add.
424 * @param <K> the type of the Key in the Key-Value store.
425 * @param <V> the type of the Value in the Key-Value store.
426 * @param typeK the type of the Key in the Key-Value store.
427 * @param typeV the type of the Value in the Key-Value store.
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800428 * @return the event channel for the channel name.
429 */
430 @Override
431 public <K, V> IEventChannel<K, V> addListener(String channelName,
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700432 IEventChannelListener<K, V> listener,
433 Class<K> typeK, Class<V> typeV) {
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700434 synchronized (eventChannels) {
435 IEventChannel<K, V> eventChannel =
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700436 createChannelImpl(channelName, typeK, typeV);
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700437 eventChannel.addListener(listener);
438 eventChannel.startup();
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800439
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700440 return eventChannel;
441 }
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800442 }
443
444 /**
445 * Remove event channel listener.
446 *
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700447 * @param <K> the type of the Key in the Key-Value store.
448 * @param <V> the type of the Value in the Key-Value store.
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800449 * @param channelName the event channel name.
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700450 * @param listener the listener to remove.
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800451 */
452 @Override
453 public <K, V> void removeListener(String channelName,
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700454 IEventChannelListener<K, V> listener) {
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700455 synchronized (eventChannels) {
456 IEventChannel<?, ?> genericEventChannel =
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700457 eventChannels.get(channelName);
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800458
Pavlin Radoslavov00fad592014-03-21 11:32:34 -0700459 if (genericEventChannel != null) {
460 //
461 // TODO: Find if we can use Java internal support to check for
462 // type mismatch.
463 // NOTE: Using "ClassCastException" exception below doesn't
464 // work.
465 //
466 IEventChannel<K, V> castedEventChannel =
467 (IEventChannel<K, V>) genericEventChannel;
468 castedEventChannel.removeListener(listener);
469 }
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700470 }
Pavlin Radoslavov7940b652014-02-13 19:42:05 -0800471 }
472
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800473 @Override
Jonathan Hartc6325622014-01-14 16:37:50 -0800474 public void registerPacketOutEventHandler(IPacketOutEventHandler packetOutEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700475 if (packetOutEventHandler != null) {
476 packetOutEventHandlers.add(packetOutEventHandler);
477 }
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800478 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800479
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800480 @Override
Jonathan Hartc6325622014-01-14 16:37:50 -0800481 public void deregisterPacketOutEventHandler(IPacketOutEventHandler packetOutEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700482 packetOutEventHandlers.remove(packetOutEventHandler);
Jonathan Hart7804bea2014-01-07 10:50:52 -0800483 }
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -0800484
Jonathan Hart7804bea2014-01-07 10:50:52 -0800485 @Override
486 public void registerArpReplyEventHandler(IArpReplyEventHandler arpReplyEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700487 if (arpReplyEventHandler != null) {
488 arpReplyEventHandlers.add(arpReplyEventHandler);
489 }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800490 }
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800491
Jonathan Hart7804bea2014-01-07 10:50:52 -0800492 @Override
493 public void deregisterArpReplyEventHandler(IArpReplyEventHandler arpReplyEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700494 arpReplyEventHandlers.remove(arpReplyEventHandler);
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800495 }
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700496
TeruU80ce5062014-03-03 17:16:13 -0800497 @Override
498 public void registerMapDeviceEventHandler(IDeviceEventHandler deviceEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700499 if (deviceEventHandler != null) {
500 deviceEventHandlers.add(deviceEventHandler);
501 }
TeruU80ce5062014-03-03 17:16:13 -0800502 }
503
504 @Override
505 public void deregisterMapDeviceEventHandler(IDeviceEventHandler deviceEventHandler) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700506 deviceEventHandlers.remove(deviceEventHandler);
TeruU80ce5062014-03-03 17:16:13 -0800507 }
Yuta HIGUCHI67a7a3e2014-01-03 14:51:34 -0800508
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800509 @Override
Jonathan Hart7804bea2014-01-07 10:50:52 -0800510 public void sendPacketOutNotification(PacketOutNotification packetOutNotification) {
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700511 packetOutMap.putAsync(packetOutNotification, dummyByte, 1L, TimeUnit.MILLISECONDS);
Jonathan Hart18ad55c2013-11-11 22:49:55 -0800512 }
Jonathan Hart7804bea2014-01-07 10:50:52 -0800513
Ray Milkey0ab2d8a2014-03-20 14:30:10 -0700514 @Override
515 public void sendArpReplyNotification(ArpReplyNotification arpReply) {
516 arpReplyMap.putAsync(arpReply, dummyByte, 1L, TimeUnit.MILLISECONDS);
517 }
518
519 @Override
520 public void sendNotificationDeviceAdded(Long mac, OnosDevice dev) {
521 log.debug("DeviceAdded in datagrid. mac {}", dev.getMacAddress());
522 mapDevice.putAsync(mac, dev);
523 }
524
525 @Override
526 public void sendNotificationDeviceDeleted(OnosDevice dev) {
527 long mac = dev.getMacAddress().toLong();
528 if (mapDevice.containsKey(mac)) {
529 log.debug("DeviceDeleted in datagrid. mac {}", dev.getMacAddress());
530 mapDevice.removeAsync(mac);
531 }
532 }
Pavlin Radoslavov1eee2c82013-10-15 02:30:32 -0700533}