blob: c17ab9cb8468b57b33c2efc8e257cb0509b79073 [file] [log] [blame]
Jonathan Hart062a2e82014-02-03 09:41:57 -08001package net.onrc.onos.ofcontroller.networkgraph;
2
Yuta HIGUCHI1c700102014-02-12 16:30:52 -08003import java.net.InetAddress;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08004import java.util.ArrayList;
5import java.util.HashSet;
6import java.util.List;
7import java.util.Set;
8
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -08009import net.onrc.onos.datastore.topology.RCLink;
Jonathan Hart062a2e82014-02-03 09:41:57 -080010import net.onrc.onos.datastore.topology.RCPort;
11import net.onrc.onos.datastore.topology.RCSwitch;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080012import net.onrc.onos.ofcontroller.networkgraph.PortEvent.SwitchPort;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080013import net.onrc.onos.ofcontroller.util.Dpid;
Jonathan Hart062a2e82014-02-03 09:41:57 -080014
15import org.slf4j.Logger;
16import org.slf4j.LoggerFactory;
17
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080018/**
19 * The "NB" read-only Network Map.
20 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080021 * - Maintain Invariant/Relationships between Topology Objects.
22 *
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080023 * TODO To be synchronized based on TopologyEvent Notification.
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080024 *
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080025 * TODO TBD: Caller is expected to maintain parent/child calling order. Parent
Yuta HIGUCHI1c700102014-02-12 16:30:52 -080026 * Object must exist before adding sub component(Add Switch -> Port).
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080027 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080028 * TODO TBD: This class may delay the requested change to handle event
29 * re-ordering. e.g.) Link Add came in, but Switch was not there.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080030 *
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080031 */
Yuta HIGUCHI928fa682014-02-11 19:07:57 -080032public class NetworkGraphImpl extends AbstractNetworkGraph implements
33 NetworkGraphDiscoveryInterface, NetworkGraphReplicationInterface {
Jonathan Hart062a2e82014-02-03 09:41:57 -080034
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080035 private static final Logger log = LoggerFactory
36 .getLogger(NetworkGraphImpl.class);
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -080037
Jonathan Hart22eb9882014-02-11 15:52:59 -080038 private final NetworkGraphDatastore datastore;
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080039
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080040 public NetworkGraphImpl() {
41 super();
Jonathan Hart22eb9882014-02-11 15:52:59 -080042 datastore = new NetworkGraphDatastore(this);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080043 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080044
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080045 /**
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080046 * put Switch
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080047 *
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080048 * XXX Internal In-memory object mutation method. Will not write to DB.
49 * Will not fire Notification.
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080050 *
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080051 * @param swEvt
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080052 */
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080053 void putSwitch(SwitchEvent swEvt) {
54 if (swEvt == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080055 throw new IllegalArgumentException("Switch cannot be null");
56 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -080057
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080058 Switch sw = switches.get(swEvt.getDpid());
59
60 if (sw == null) {
61 sw = new SwitchImpl(this, swEvt.getDpid());
62 Switch existing = switches.putIfAbsent(swEvt.getDpid(), sw);
63 if (existing != null) {
64 log.warn(
65 "Concurrent putSwitch not expected. Continuing updating {}",
66 existing);
67 sw = existing;
68 }
69 }
70
Yuta HIGUCHId02e9282014-02-12 09:24:41 -080071 // Update when more attributes are added to Event object
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080072 // no attribute to update for now
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -080073
74 // TODO handle child Port event properly for performance
75 for (PortEvent portEvt : swEvt.getPorts() ) {
76 putPort(portEvt);
77 }
78
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080079 }
80
81 /**
82 * remove Switch.
83 *
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080084 * XXX Internal In-memory object mutation method. Will not write to DB.
85 * Will not fire Notification.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080086 *
87 * @param swEvt
88 */
89 void removeSwitch(SwitchEvent swEvt) {
90 if (swEvt == null) {
91 throw new IllegalArgumentException("Switch cannot be null");
92 }
93
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -080094 // TODO handle child Port event properly for performance
95 for (PortEvent portEvt : swEvt.getPorts() ) {
96 removePort(portEvt);
97 }
98
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080099 Switch sw = switches.get(swEvt.getDpid());
100
101 if (sw == null) {
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800102 log.warn("Switch {} already removed, ignoring", swEvt);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800103 return;
104 }
105
106 // Sanity check
107 if (!sw.getPorts().isEmpty()) {
108 log.warn(
109 "Ports on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
110 swEvt);
111 // XXX Should we remove Port?
112 }
113 if (!sw.getDevices().isEmpty()) {
114 log.warn(
115 "Devices on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
116 swEvt);
117 // XXX Should we remove Device to Switch relation?
118 }
119 if (!sw.getIncomingLinks().iterator().hasNext()) {
120 log.warn(
121 "IncomingLinks on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
122 swEvt);
123 // XXX Should we remove Link?
124 }
125 if (!sw.getOutgoingLinks().iterator().hasNext()) {
126 log.warn(
127 "OutgoingLinks on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
128 swEvt);
129 // XXX Should we remove Link?
130 }
131
132 boolean removed = switches.remove(swEvt.getDpid(), sw);
133 if (removed) {
134 log.warn(
135 "Switch instance was replaced concurrently while removing {}. Something is not right.",
136 sw);
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800137 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800138 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -0800139
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800140 /**
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800141 * put Port
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800142 *
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800143 * XXX Internal In-memory object mutation method. Will not write to DB.
144 * Will not fire Notification.
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800145 *
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800146 * @param portEvt
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800147 */
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800148 void putPort(PortEvent portEvt) {
149 if (portEvt == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800150 throw new IllegalArgumentException("Port cannot be null");
151 }
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800152 Switch sw = switches.get(portEvt.getDpid());
153 if (sw == null) {
154 throw new BrokenInvariantException(String.format(
155 "Switch with dpid %s did not exist.",
156 new Dpid(portEvt.getDpid())));
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800157 }
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800158 Port p = sw.getPort(portEvt.getNumber());
159 PortImpl port = null;
160 if (p != null) {
161 port = getPortImpl(p);
162 }
163
164 if (port == null) {
165 port = new PortImpl(this, sw, portEvt.getNumber());
166 }
167
168 // TODO update attributes
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800169
170 SwitchImpl s = getSwitchImpl(sw);
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800171 s.addPort(port);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800172 }
173
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800174 /**
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800175 * remove Port
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800176 *
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800177 * XXX Internal In-memory object mutation method. Will not write to DB.
178 * Will not fire Notification.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800179 *
180 * @param portEvt
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800181 */
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800182 void removePort(PortEvent portEvt) {
183 if (portEvt == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800184 throw new IllegalArgumentException("Port cannot be null");
185 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800186
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800187 Switch sw = switches.get(portEvt.getDpid());
188 if (sw == null) {
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800189 log.warn("Parent Switch for Port {} already removed, ignoring", portEvt);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800190 return;
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800191 }
192
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800193 Port p = sw.getPort(portEvt.getNumber());
194 if (p == null) {
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800195 log.warn("Port {} already removed, ignoring", portEvt);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800196 return;
197 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800198
199 // check if there is something referring to this Port
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800200
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800201 if (!p.getDevices().iterator().hasNext()) {
202 log.warn(
203 "Devices on Port {} should be removed prior to removing Port. Removing Port anyways",
204 portEvt);
205 // XXX Should we remove Device to Port relation?
206 }
207 if (p.getIncomingLink() != null) {
208 log.warn(
209 "IncomingLinks on Port {} should be removed prior to removing Port. Removing Port anyways",
210 portEvt);
211 // XXX Should we remove Link?
212 }
213 if (p.getOutgoingLink() != null) {
214 log.warn(
215 "OutgoingLinks on Port {} should be removed prior to removing Port. Removing Port anyways",
216 portEvt);
217 // XXX Should we remove Link?
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800218 }
219
220 // remove Port from Switch
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800221 SwitchImpl s = getSwitchImpl(sw);
222 s.removePort(p);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800223 }
224
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800225 /**
226 * put Link
227 *
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800228 * XXX Internal In-memory object mutation method. Will not write to DB.
229 * Will not fire Notification.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800230 *
231 * @param linkEvt
232 */
233 void putLink(LinkEvent linkEvt) {
234 if (linkEvt == null) {
235 throw new IllegalArgumentException("Link cannot be null");
236 }
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800237
238 Switch srcSw = switches.get(linkEvt.getSrc().dpid);
239 if (srcSw == null) {
240 throw new BrokenInvariantException(
241 String.format(
242 "Switch with dpid %s did not exist.",
243 new Dpid(linkEvt.getSrc().dpid)));
244 }
245
246 Switch dstSw = switches.get(linkEvt.getDst().dpid);
247 if (dstSw == null) {
248 throw new BrokenInvariantException(
249 String.format(
250 "Switch with dpid %s did not exist.",
251 new Dpid(linkEvt.getDst().dpid)));
252 }
253
254 Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
255 if (srcPort == null) {
256 throw new BrokenInvariantException(
257 String.format(
258 "Src Port %s of a Link did not exist.",
259 linkEvt.getSrc() ));
260 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800261
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800262 Port dstPort = dstSw.getPort(linkEvt.getDst().number);
263 if (dstPort == null) {
264 throw new BrokenInvariantException(
265 String.format(
266 "Dst Port %s of a Link did not exist.",
267 linkEvt.getDst() ));
268 }
269
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800270 // getting Link instance from destination port incoming Link
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800271 Link l = dstPort.getIncomingLink();
272 LinkImpl link = null;
273 assert( l == srcPort.getOutgoingLink() );
274 if (l != null) {
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800275 link = getLinkImpl(l);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800276 }
277
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800278 if (link == null) {
279 link = new LinkImpl(this, srcPort, dstPort);
280 }
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800281
282
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800283 PortImpl dstPortMem = getPortImpl(dstPort);
284 PortImpl srcPortMem = getPortImpl(srcPort);
285
286 // Add Link first to avoid further Device addition
287
288 // add Link to Port
289 dstPortMem.setIncomingLink(link);
290 srcPortMem.setOutgoingLink(link);
291
292 // remove Device Pointing to Port if any
293 for(Device d : dstPortMem.getDevices() ) {
294 log.error("Device {} on Port {} should have been removed prior to adding Link {}", d, dstPort, linkEvt);
295 DeviceImpl dev = getDeviceImpl(d);
296 dev.removeAttachmentPoint(dstPort);
297 // XXX This implies that change is made to Device Object,
298 // which need to be written to DB, how should that be done?
299 // should we write here or ignore and leave DB in inconsistent state?
300 }
301 dstPortMem.removeAllDevice();
302 for(Device d : srcPortMem.getDevices() ) {
303 log.error("Device {} on Port {} should have been removed prior to adding Link {}", d, srcPort, linkEvt);
304 DeviceImpl dev = getDeviceImpl(d);
305 dev.removeAttachmentPoint(srcPort);
306 // XXX This implies that change is made to Device Object,
307 // which need to be written to DB, how should that be done?
308 // should we write here or ignore and leave DB in inconsistent state?
309 }
310 srcPortMem.removeAllDevice();
311
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800312 }
313
314 /**
315 * removeLink
316 *
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800317 * XXX Internal In-memory object mutation method. Will not write to DB.
318 * Will not fire Notification.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800319 *
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800320 * @param linkEvt
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800321 */
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800322 void removeLink(LinkEvent linkEvt) {
323 if (linkEvt == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800324 throw new IllegalArgumentException("Link cannot be null");
325 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800326
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800327 Switch srcSw = switches.get(linkEvt.getSrc().dpid);
328 if (srcSw == null) {
329 log.warn("Src Switch for Link {} already removed, ignoring", linkEvt);
330 return;
331 }
332
333 Switch dstSw = switches.get(linkEvt.getDst().dpid);
334 if (dstSw == null) {
335 log.warn("Dst Switch for Link {} already removed, ignoring", linkEvt);
336 return;
337 }
338
339 Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
340 if (srcPort == null) {
341 log.warn("Src Port for Link {} already removed, ignoring", linkEvt);
342 return;
343 }
344
345 Port dstPort = dstSw.getPort(linkEvt.getDst().number);
346 if (dstPort == null) {
347 log.warn("Dst Port for Link {} already removed, ignoring", linkEvt);
348 return;
349 }
350
351 Link l = dstPort.getIncomingLink();
352 if ( l == null ) {
353 log.warn("Link {} already removed on destination Port", linkEvt);
354 }
355 l = srcPort.getOutgoingLink();
356 if ( l == null ) {
357 log.warn("Link {} already removed on src Port", linkEvt);
358 }
359
360 getPortImpl(dstPort).setIncomingLink(null);
361 getPortImpl(srcPort).setOutgoingLink(null);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800362 }
363
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800364 // XXX Need to rework Device related
365 /**
366 * Add new device to DB
367 *
368 * @param device
369 */
Yuta HIGUCHI0be4a662014-02-11 18:01:28 -0800370 void putDevice(DeviceEvent deviceEvt) {
371 if (deviceEvt == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800372 throw new IllegalArgumentException("Device cannot be null");
373 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800374
Yuta HIGUCHI1c700102014-02-12 16:30:52 -0800375 Device device = getDeviceByMac(deviceEvt.getMac());
376 if ( device == null ) {
377 device = new DeviceImpl(this, deviceEvt.getMac());
378 Device existing = mac2Device.putIfAbsent(deviceEvt.getMac(), device);
379 if (existing != null) {
380 log.warn(
381 "Concurrent putDevice seems to be in action. Continuing updating {}",
382 existing);
383 device = existing;
384 }
385 }
386 DeviceImpl memDevice = getDeviceImpl(device);
387
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800388 // for each attachment point
Yuta HIGUCHI1c700102014-02-12 16:30:52 -0800389 for (SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
390 // Attached Ports' Parent Switch must exist
391 Switch sw = getSwitch(swp.dpid);
392 if ( sw == null ) {
393 log.warn("Switch {} for the attachment point did not exist. skipping mutation", sw);
394 continue;
395 }
396 // Attached Ports must exist
397 Port port = sw.getPort(swp.number);
398 if ( port == null ) {
399 log.warn("Port {} for the attachment point did not exist. skipping mutation", port);
400 continue;
401 }
402 // Attached Ports must not have Link
403 if ( port.getOutgoingLink() != null || port.getIncomingLink() != null ) {
404 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.", port.getOutgoingLink(), port.getIncomingLink());
405 continue;
406 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800407
Yuta HIGUCHI1c700102014-02-12 16:30:52 -0800408 // finally add Device <-> Port on In-memory structure
409 PortImpl memPort = getPortImpl(port);
410 memPort.addDevice(device);
411 memDevice.addAttachmentPoint(port);
412 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800413
Yuta HIGUCHI1c700102014-02-12 16:30:52 -0800414 // for each IP address
415 for( InetAddress ipAddr : deviceEvt.getIpAddresses() ) {
416 // Add Device -> IP
417 memDevice.addIpAddress(ipAddr);
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800418
Yuta HIGUCHI1c700102014-02-12 16:30:52 -0800419 // Add IP -> Set<Device>
420 boolean updated = false;
421 do {
422 Set<Device> devices = this.addr2Device.get(ipAddr);
423 if ( devices == null ) {
424 devices = new HashSet<>();
425 Set<Device> existing = this.addr2Device.putIfAbsent(ipAddr, devices);
426 if ( existing == null ) {
427 // success
428 updated = true;
429 }
430 } else {
431 Set<Device> updateDevices = new HashSet<>(devices);
432 updateDevices.add(device);
433 updated = this.addr2Device.replace(ipAddr, devices, updateDevices);
434 }
435 if (!updated) {
436 log.debug("Collision detected, updating IP to Device mapping retrying.");
437 }
438 } while( !updated );
439 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800440 }
441
Yuta HIGUCHI1c700102014-02-12 16:30:52 -0800442 void removeDevice(DeviceEvent deviceEvt) {
443 if (deviceEvt == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800444 throw new IllegalArgumentException("Device cannot be null");
445 }
Yuta HIGUCHI1c700102014-02-12 16:30:52 -0800446
447 Device device = getDeviceByMac(deviceEvt.getMac());
448 if ( device == null ) {
449 log.warn("Device {} already removed, ignoring", deviceEvt);
450 return;
451 }
452 DeviceImpl memDevice = getDeviceImpl(device);
453
454 // for each attachment point
455 for (SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
456 // Attached Ports' Parent Switch must exist
457 Switch sw = getSwitch(swp.dpid);
458 if ( sw == null ) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800459 log.warn("Switch {} for the attachment point did not exist. skipping attachment point mutation", sw);
Yuta HIGUCHI1c700102014-02-12 16:30:52 -0800460 continue;
461 }
462 // Attached Ports must exist
463 Port port = sw.getPort(swp.number);
464 if ( port == null ) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800465 log.warn("Port {} for the attachment point did not exist. skipping attachment point mutation", port);
Yuta HIGUCHI1c700102014-02-12 16:30:52 -0800466 continue;
467 }
468
469 // finally remove Device <-> Port on In-memory structure
470 PortImpl memPort = getPortImpl(port);
471 memPort.removeDevice(device);
472 memDevice.removeAttachmentPoint(port);
473 }
474
475 // for each IP address
476 for( InetAddress ipAddr : deviceEvt.getIpAddresses() ) {
477 // Remove Device -> IP
478 memDevice.removeIpAddress(ipAddr);
479
480 // Remove IP -> Set<Device>
481 boolean updated = false;
482 do {
483 Set<Device> devices = this.addr2Device.get(ipAddr);
484 if ( devices == null ) {
485 // already empty set, nothing to do
486 updated = true;
487 } else {
488 Set<Device> updateDevices = new HashSet<>(devices);
489 updateDevices.remove(device);
490 updated = this.addr2Device.replace(ipAddr, devices, updateDevices);
491 }
492 if (!updated) {
493 log.debug("Collision detected, updating IP to Device mapping retrying.");
494 }
495 } while( !updated );
496 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800497 }
498
499 private SwitchImpl getSwitchImpl(Switch sw) {
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800500 if (sw instanceof SwitchImpl) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800501 return (SwitchImpl) sw;
502 }
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800503 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
504 }
505
506 private PortImpl getPortImpl(Port p) {
507 if (p instanceof PortImpl) {
508 return (PortImpl) p;
509 }
510 throw new ClassCastException("PortImpl expected, but found: " + p);
511 }
512
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800513 private LinkImpl getLinkImpl(Link l) {
514 if (l instanceof LinkImpl) {
515 return (LinkImpl) l;
516 }
517 throw new ClassCastException("LinkImpl expected, but found: " + l);
518 }
519
Yuta HIGUCHIc0366272014-02-10 21:04:57 -0800520 private DeviceImpl getDeviceImpl(Device d) {
521 if (d instanceof DeviceImpl) {
522 return (DeviceImpl) d;
523 }
524 throw new ClassCastException("DeviceImpl expected, but found: " + d);
525 }
526
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800527 public void loadWholeTopologyFromDB() {
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800528 // TODO this method needs to use East-bound API if we still need this
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800529 // XXX clear everything first?
530
531 for (RCSwitch sw : RCSwitch.getAllSwitches()) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800532 if ( sw.getStatus() != RCSwitch.STATUS.ACTIVE ) {
533 continue;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800534 }
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800535 putSwitchReplicationEvent(new SwitchEvent(sw.getDpid()));
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800536 }
537
538 for (RCPort p : RCPort.getAllPorts()) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800539 if (p.getStatus() != RCPort.STATUS.ACTIVE) {
540 continue;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800541 }
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800542 putPortReplicationEvent(new PortEvent(p.getDpid(), p.getNumber() ));
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800543 }
544
545 // TODO Is Device going to be in DB? If so, read from DB.
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800546 // for (RCDevice d : RCDevice.getAllDevices()) {
547 // DeviceEvent devEvent = new DeviceEvent( MACAddress.valueOf(d.getMac()) );
548 // for (byte[] portId : d.getAllPortIds() ) {
549 // devEvent.addAttachmentPoint( new SwitchPort( RCPort.getDpidFromKey(portId), RCPort.getNumberFromKey(portId) ));
550 // }
551 // }
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800552
553 for (RCLink l : RCLink.getAllLinks()) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800554 putLinkReplicationEvent( new LinkEvent(l.getSrc().dpid, l.getSrc().number, l.getDst().dpid, l.getDst().number));
Jonathan Hart062a2e82014-02-03 09:41:57 -0800555 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800556 }
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800557
558 /**
559 * Exception to be thrown when Modification to the Network Graph cannot be continued due to broken invariant.
560 *
561 * XXX Should this be checked exception or RuntimeException
562 */
563 public static class BrokenInvariantException extends RuntimeException {
564 private static final long serialVersionUID = 1L;
565
566 public BrokenInvariantException() {
567 super();
568 }
569
570 public BrokenInvariantException(String message) {
571 super(message);
572 }
573 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800574
575 /* ******************************
576 * NetworkGraphDiscoveryInterface methods
577 * ******************************/
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800578
Jonathan Hart22eb9882014-02-11 15:52:59 -0800579 @Override
580 public void putSwitchEvent(SwitchEvent switchEvent) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800581 if (prepareForAddSwitchEvent(switchEvent)) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800582 datastore.addSwitch(switchEvent);
583 putSwitch(switchEvent);
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800584 // TODO send out notification
Jonathan Hart22eb9882014-02-11 15:52:59 -0800585 }
586 // TODO handle invariant violation
587 }
588
589 @Override
590 public void removeSwitchEvent(SwitchEvent switchEvent) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800591 if (prepareForRemoveSwitchEvent(switchEvent)) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800592 datastore.deactivateSwitch(switchEvent);
593 removeSwitch(switchEvent);
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800594 // TODO send out notification
Jonathan Hart22eb9882014-02-11 15:52:59 -0800595 }
596 // TODO handle invariant violation
597 }
598
599 @Override
600 public void putPortEvent(PortEvent portEvent) {
601 // TODO Auto-generated method stub
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800602
Jonathan Hart22eb9882014-02-11 15:52:59 -0800603 }
604
605 @Override
606 public void removePortEvent(PortEvent portEvent) {
607 // TODO Auto-generated method stub
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800608
Jonathan Hart22eb9882014-02-11 15:52:59 -0800609 }
610
611 @Override
612 public void putLinkEvent(LinkEvent linkEvent) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800613 if (prepareForAddLinkEvent(linkEvent)) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800614 datastore.addLink(linkEvent);
615 putLink(linkEvent);
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800616 // TODO send out notification
Jonathan Hart22eb9882014-02-11 15:52:59 -0800617 }
618 // TODO handle invariant violation
619 }
620
621 @Override
622 public void removeLinkEvent(LinkEvent linkEvent) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800623 if (prepareForRemoveLinkEvent(linkEvent)) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800624 datastore.removeLink(linkEvent);
625 removeLink(linkEvent);
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800626 // TODO send out notification
Jonathan Hart22eb9882014-02-11 15:52:59 -0800627 }
628 // TODO handle invariant violation
629 }
630
631 @Override
Yuta HIGUCHI0be4a662014-02-11 18:01:28 -0800632 public void putDeviceEvent(DeviceEvent device) {
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800633 // XXX if prepareFor~ method returned false, event should be dropped
Jonathan Hart22eb9882014-02-11 15:52:59 -0800634 // TODO Auto-generated method stub
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800635
Jonathan Hart22eb9882014-02-11 15:52:59 -0800636 }
637
638 @Override
639 public void removeDeviceEvent(DeviceEvent deviceEvent) {
640 // TODO Auto-generated method stub
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800641
Jonathan Hart22eb9882014-02-11 15:52:59 -0800642 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800643
Jonathan Hart22eb9882014-02-11 15:52:59 -0800644 /* *****************
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800645 * Internal methods to maintain invariants of the network graph
Jonathan Hart22eb9882014-02-11 15:52:59 -0800646 * *****************/
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800647
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800648 /**
649 *
650 * @param swEvt
651 * @return true if ready to accept event.
652 */
653 private boolean prepareForAddSwitchEvent(SwitchEvent swEvt) {
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800654 // No show stopping precondition?
655 // Prep: remove(deactivate) Ports on Switch, which is not on event
656 removePortsNotOnEvent(swEvt);
657 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800658 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800659
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800660 private boolean prepareForRemoveSwitchEvent(SwitchEvent swEvt) {
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800661 // No show stopping precondition?
662 // Prep: remove(deactivate) Ports on Switch, which is not on event
663 // XXX may be remove switch should imply wipe all ports
664 removePortsNotOnEvent(swEvt);
665 return true;
666 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800667
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800668 private void removePortsNotOnEvent(SwitchEvent swEvt) {
669 Switch sw = switches.get( swEvt.getDpid() );
670 if ( sw != null ) {
671 Set<Long> port_noOnEvent = new HashSet<>();
672 for( PortEvent portEvent : swEvt.getPorts()) {
673 port_noOnEvent.add(portEvent.getNumber());
674 }
675 // Existing ports not on event should be removed.
676 // TODO Should batch eventually for performance?
677 for( Port p : sw.getPorts() ) {
678 if ( !port_noOnEvent.contains(p.getNumber()) ) {
679 PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(), p.getNumber());
680 // calling Discovery removePort() API to wipe from DB, etc.
681 removePortEvent(rmEvent);
682 }
683 }
684 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800685 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800686
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800687 private boolean prepareForAddPortEvent(PortEvent portEvt) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800688 // Parent Switch must exist
689 if ( getSwitch(portEvt.getDpid()) == null) {
690 return false;
691 }
692 // Prep: None
Jonathan Hart22eb9882014-02-11 15:52:59 -0800693 return true;
694 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800695
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800696 private boolean prepareForRemovePortEvent(PortEvent portEvt) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800697 // Parent Switch must exist
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800698 Switch sw = getSwitch(portEvt.getDpid());
699 if ( sw == null ) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800700 return false;
701 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800702 Port port = sw.getPort(portEvt.getNumber());
703 if ( port == null ) {
704 log.debug("Port already removed? {}", portEvt);
705 // let it pass
706 return true;
707 }
708
709 // Prep: Remove Link and Device Attachment
710 for (Device device : port.getDevices()) {
711 DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
712 devEvt.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(), port.getNumber()));
713 // calling Discovery API to wipe from DB, etc.
714 removeDeviceEvent(devEvt);
715 }
716 Set<Link> links = new HashSet<>();
717 links.add(port.getOutgoingLink());
718 links.add(port.getIncomingLink());
719 for ( Link link : links) {
720 if (link == null ) {
721 continue;
722 }
723 LinkEvent linkEvent = new LinkEvent(link.getSourceSwitchDpid(), link.getSourcePortNumber(), link.getDestinationSwitchDpid(), link.getDestinationPortNumber());
724 // calling Discovery API to wipe from DB, etc.
725 removeLinkEvent(linkEvent);
726 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800727 return true;
728 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800729
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800730 private boolean prepareForAddLinkEvent(LinkEvent linkEvt) {
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800731 // Src/Dst Switch must exist
732 Switch srcSw = getSwitch(linkEvt.getSrc().dpid);
733 Switch dstSw = getSwitch(linkEvt.getDst().dpid);
734 if ( srcSw == null || dstSw == null ) {
735 return false;
736 }
737 // Src/Dst Port must exist
738 Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
739 Port dstPort = srcSw.getPort(linkEvt.getDst().number);
740 if ( srcPort == null || dstPort == null ) {
741 return false;
742 }
743
744 // Prep: remove Device attachment on both Ports
745 for (Device device : srcPort.getDevices()) {
746 DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
747 devEvt.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
748 // calling Discovery API to wipe from DB, etc.
749 removeDeviceEvent(devEvt);
750 }
751 for (Device device : dstPort.getDevices()) {
752 DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
753 devEvt.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(), dstPort.getNumber()));
754 // calling Discovery API to wipe from DB, etc.
755 removeDeviceEvent(devEvt);
756 }
757
758 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800759 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800760
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800761 private boolean prepareForRemoveLinkEvent(LinkEvent linkEvt) {
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800762 // Src/Dst Switch must exist
763 Switch srcSw = getSwitch(linkEvt.getSrc().dpid);
764 Switch dstSw = getSwitch(linkEvt.getDst().dpid);
765 if ( srcSw == null || dstSw == null ) {
766 return false;
767 }
768 // Src/Dst Port must exist
769 Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
770 Port dstPort = srcSw.getPort(linkEvt.getDst().number);
771 if ( srcPort == null || dstPort == null ) {
772 return false;
773 }
774
775 // Prep: None
776 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800777 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800778
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800779 /**
780 *
781 * @param deviceEvt Event will be modified to remove inapplicable attachemntPoints/ipAddress
782 * @return false if this event should be dropped.
783 */
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800784 private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvt) {
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800785 boolean preconditionBroken = false;
786 ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
787 for ( PortEvent.SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800788 // Attached Ports' Parent Switch must exist
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800789 Switch sw = getSwitch(swp.dpid);
790 if ( sw == null ) {
791 preconditionBroken = true;
792 failedSwitchPort.add(swp);
793 continue;
794 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800795 // Attached Ports must exist
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800796 Port port = sw.getPort(swp.number);
797 if ( port == null ) {
798 preconditionBroken = true;
799 failedSwitchPort.add(swp);
800 continue;
801 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800802 // Attached Ports must not have Link
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800803 if ( port.getOutgoingLink() != null || port.getIncomingLink() != null ) {
804 preconditionBroken = true;
805 failedSwitchPort.add(swp);
806 continue;
807 }
808 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800809
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800810 // Rewriting event to exclude failed attachmentPoint
811 // XXX Assumption behind this is that inapplicable device event should
812 // be dropped, not deferred. If we decide to defer Device event,
813 // rewriting can become a problem
814 List<SwitchPort> attachmentPoints = deviceEvt.getAttachmentPoints();
815 attachmentPoints.removeAll(failedSwitchPort);
816 deviceEvt.setAttachmentPoints(attachmentPoints);
817
818 if ( deviceEvt.getAttachmentPoints().isEmpty() && deviceEvt.getIpAddresses().isEmpty() ) {
819 // XXX return false to represent: Nothing left to do for this event. Caller should drop event
820 return false;
821 }
822
823 // Should we return false to tell caller that the event was trimmed?
824 // if ( preconditionBroken ) {
825 // return false;
826 // }
827
828 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800829 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800830
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800831 private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvt) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800832 // No show stopping precondition?
833 // Prep: none
Jonathan Hart22eb9882014-02-11 15:52:59 -0800834 return true;
835 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800836
837 @Override
838 public void putSwitchReplicationEvent(SwitchEvent switchEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800839 // TODO who is in charge of ignoring event triggered by my self?
840 // This method or caller?
841 if (prepareForAddSwitchEvent(switchEvent)) {
842 putSwitch(switchEvent);
843 }
844 // TODO handle invariant violation
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800845 }
846
847 @Override
848 public void removeSwitchReplicationEvent(SwitchEvent switchEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800849 // TODO who is in charge of ignoring event triggered by my self?
850 // This method or caller?
851 if (prepareForRemoveSwitchEvent(switchEvent)) {
852 removeSwitch(switchEvent);
853 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800854 // TODO Auto-generated method stub
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800855 }
856
857 @Override
858 public void putPortReplicationEvent(PortEvent portEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800859 // TODO who is in charge of ignoring event triggered by my self?
860 // This method or caller?
861 if (prepareForAddPortEvent(portEvent)) {
862 putPort(portEvent);
863 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800864 // TODO Auto-generated method stub
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800865 }
866
867 @Override
868 public void removePortReplicationEvent(PortEvent portEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800869 // TODO who is in charge of ignoring event triggered by my self?
870 // This method or caller?
871 if (prepareForRemovePortEvent(portEvent)) {
872 removePort(portEvent);
873 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800874 // TODO Auto-generated method stub
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800875 }
876
877 @Override
878 public void putLinkReplicationEvent(LinkEvent linkEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800879 // TODO who is in charge of ignoring event triggered by my self?
880 // This method or caller?
881 if (prepareForAddLinkEvent(linkEvent)) {
882 putLink(linkEvent);
883 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800884 // TODO Auto-generated method stub
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800885 }
886
887 @Override
888 public void removeLinkReplicationEvent(LinkEvent linkEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800889 // TODO who is in charge of ignoring event triggered by my self?
890 // This method or caller?
891 if (prepareForRemoveLinkEvent(linkEvent)) {
892 removeLink(linkEvent);
893 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800894 // TODO Auto-generated method stub
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800895 }
896
897 @Override
898 public void putDeviceReplicationEvent(DeviceEvent deviceEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800899 // TODO who is in charge of ignoring event triggered by my self?
900 // This method or caller?
901 if (prepareForAddDeviceEvent(deviceEvent)) {
902 putDevice(deviceEvent);
903 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800904 // TODO Auto-generated method stub
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800905 }
906
907 @Override
908 public void removeDeviceReplicationEvent(DeviceEvent deviceEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800909 // TODO who is in charge of ignoring event triggered by my self?
910 // This method or caller?
911 if (prepareForRemoveDeviceEvent(deviceEvent)) {
912 removeDevice(deviceEvent);
913 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800914 // TODO Auto-generated method stub
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800915 }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800916}