Thomas Vachuska

Fixed objective tracker not to do extra work so eagerly.

Added ability to see availability status as part of device events (for availability events)

Change-Id: I4a3476e203459ed72deee45f0a24e4b4373bd819
...@@ -20,7 +20,10 @@ import org.onosproject.event.AbstractEvent; ...@@ -20,7 +20,10 @@ import org.onosproject.event.AbstractEvent;
20 import org.onosproject.net.Device; 20 import org.onosproject.net.Device;
21 import org.onosproject.net.Port; 21 import org.onosproject.net.Port;
22 22
23 +import java.util.Optional;
24 +
23 import static com.google.common.base.MoreObjects.toStringHelper; 25 import static com.google.common.base.MoreObjects.toStringHelper;
26 +import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
24 27
25 /** 28 /**
26 * Describes infrastructure device event. 29 * Describes infrastructure device event.
...@@ -28,6 +31,7 @@ import static com.google.common.base.MoreObjects.toStringHelper; ...@@ -28,6 +31,7 @@ import static com.google.common.base.MoreObjects.toStringHelper;
28 public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> { 31 public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> {
29 32
30 private final Port port; 33 private final Port port;
34 + private final boolean isAvailable;
31 35
32 /** 36 /**
33 * Type of device events. 37 * Type of device events.
...@@ -102,6 +106,20 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> { ...@@ -102,6 +106,20 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> {
102 public DeviceEvent(Type type, Device device, Port port) { 106 public DeviceEvent(Type type, Device device, Port port) {
103 super(type, device); 107 super(type, device);
104 this.port = port; 108 this.port = port;
109 + this.isAvailable = false;
110 + }
111 +
112 + /**
113 + * Creates an event for change of device availability for the given device
114 + * and the current time.
115 + *
116 + * @param device event device subject
117 + * @param isAvailable true if device became available; false otherwise
118 + */
119 + public DeviceEvent(Device device, boolean isAvailable) {
120 + super(DEVICE_AVAILABILITY_CHANGED, device);
121 + this.port = null;
122 + this.isAvailable = isAvailable;
105 } 123 }
106 124
107 /** 125 /**
...@@ -115,6 +133,7 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> { ...@@ -115,6 +133,7 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> {
115 public DeviceEvent(Type type, Device device, Port port, long time) { 133 public DeviceEvent(Type type, Device device, Port port, long time) {
116 super(type, device, time); 134 super(type, device, time);
117 this.port = port; 135 this.port = port;
136 + this.isAvailable = false;
118 } 137 }
119 138
120 /** 139 /**
...@@ -126,6 +145,15 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> { ...@@ -126,6 +145,15 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> {
126 return port; 145 return port;
127 } 146 }
128 147
148 + /**
149 + * Indicates whether device became available or unavailable.
150 + *
151 + * @return if present, true indicates device came online; false if device went offline
152 + */
153 + public Optional<Boolean> isAvailable() {
154 + return type() == DEVICE_AVAILABILITY_CHANGED ? Optional.of(isAvailable) : Optional.empty();
155 + }
156 +
129 @Override 157 @Override
130 public String toString() { 158 public String toString() {
131 if (port == null) { 159 if (port == null) {
...@@ -137,5 +165,5 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> { ...@@ -137,5 +165,5 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> {
137 .add("subject", subject()) 165 .add("subject", subject())
138 .add("port", port) 166 .add("port", port)
139 .toString(); 167 .toString();
140 - } 168 + }
141 } 169 }
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
16 package org.onosproject.net.intent.impl; 16 package org.onosproject.net.intent.impl;
17 17
18 import com.google.common.collect.HashMultimap; 18 import com.google.common.collect.HashMultimap;
19 -import com.google.common.collect.ImmutableSet;
20 import com.google.common.collect.SetMultimap; 19 import com.google.common.collect.SetMultimap;
20 +import com.google.common.collect.Sets;
21 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
22 import org.apache.felix.scr.annotations.Component; 22 import org.apache.felix.scr.annotations.Component;
23 import org.apache.felix.scr.annotations.Deactivate; 23 import org.apache.felix.scr.annotations.Deactivate;
...@@ -25,8 +25,9 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -25,8 +25,9 @@ import org.apache.felix.scr.annotations.Reference;
25 import org.apache.felix.scr.annotations.ReferenceCardinality; 25 import org.apache.felix.scr.annotations.ReferenceCardinality;
26 import org.apache.felix.scr.annotations.ReferencePolicy; 26 import org.apache.felix.scr.annotations.ReferencePolicy;
27 import org.apache.felix.scr.annotations.Service; 27 import org.apache.felix.scr.annotations.Service;
28 +import org.onlab.util.AbstractAccumulator;
29 +import org.onlab.util.Accumulator;
28 import org.onosproject.event.Event; 30 import org.onosproject.event.Event;
29 -import org.onosproject.net.DeviceId;
30 import org.onosproject.net.ElementId; 31 import org.onosproject.net.ElementId;
31 import org.onosproject.net.HostId; 32 import org.onosproject.net.HostId;
32 import org.onosproject.net.Link; 33 import org.onosproject.net.Link;
...@@ -34,18 +35,17 @@ import org.onosproject.net.LinkKey; ...@@ -34,18 +35,17 @@ import org.onosproject.net.LinkKey;
34 import org.onosproject.net.NetworkResource; 35 import org.onosproject.net.NetworkResource;
35 import org.onosproject.net.PortNumber; 36 import org.onosproject.net.PortNumber;
36 import org.onosproject.net.device.DeviceEvent; 37 import org.onosproject.net.device.DeviceEvent;
37 -import org.onosproject.net.device.DeviceListener;
38 import org.onosproject.net.device.DeviceService; 38 import org.onosproject.net.device.DeviceService;
39 import org.onosproject.net.host.HostEvent; 39 import org.onosproject.net.host.HostEvent;
40 import org.onosproject.net.host.HostListener; 40 import org.onosproject.net.host.HostListener;
41 import org.onosproject.net.host.HostService; 41 import org.onosproject.net.host.HostService;
42 import org.onosproject.net.intent.Intent; 42 import org.onosproject.net.intent.Intent;
43 import org.onosproject.net.intent.IntentData; 43 import org.onosproject.net.intent.IntentData;
44 -import org.onosproject.net.intent.IntentService;
45 -import org.onosproject.net.intent.Key;
46 import org.onosproject.net.intent.IntentPartitionEvent; 44 import org.onosproject.net.intent.IntentPartitionEvent;
47 import org.onosproject.net.intent.IntentPartitionEventListener; 45 import org.onosproject.net.intent.IntentPartitionEventListener;
48 import org.onosproject.net.intent.IntentPartitionService; 46 import org.onosproject.net.intent.IntentPartitionService;
47 +import org.onosproject.net.intent.IntentService;
48 +import org.onosproject.net.intent.Key;
49 import org.onosproject.net.link.LinkEvent; 49 import org.onosproject.net.link.LinkEvent;
50 import org.onosproject.net.resource.ResourceEvent; 50 import org.onosproject.net.resource.ResourceEvent;
51 import org.onosproject.net.resource.ResourceListener; 51 import org.onosproject.net.resource.ResourceListener;
...@@ -57,26 +57,22 @@ import org.slf4j.Logger; ...@@ -57,26 +57,22 @@ import org.slf4j.Logger;
57 57
58 import java.util.Collection; 58 import java.util.Collection;
59 import java.util.Collections; 59 import java.util.Collections;
60 -import java.util.HashSet;
61 import java.util.List; 60 import java.util.List;
62 import java.util.Set; 61 import java.util.Set;
63 -import java.util.concurrent.ExecutorService; 62 +import java.util.Timer;
64 -import java.util.concurrent.Executors; 63 +import java.util.TimerTask;
65 -import java.util.concurrent.ScheduledExecutorService;
66 -import java.util.concurrent.TimeUnit;
67 import java.util.concurrent.atomic.AtomicBoolean; 64 import java.util.concurrent.atomic.AtomicBoolean;
68 65
69 import static com.google.common.base.Preconditions.checkArgument; 66 import static com.google.common.base.Preconditions.checkArgument;
70 import static com.google.common.base.Preconditions.checkNotNull; 67 import static com.google.common.base.Preconditions.checkNotNull;
71 import static com.google.common.collect.Multimaps.synchronizedSetMultimap; 68 import static com.google.common.collect.Multimaps.synchronizedSetMultimap;
72 -import static java.util.concurrent.Executors.newSingleThreadExecutor;
73 -import static org.onlab.util.Tools.groupedThreads;
74 import static org.onlab.util.Tools.isNullOrEmpty; 69 import static org.onlab.util.Tools.isNullOrEmpty;
75 import static org.onosproject.net.LinkKey.linkKey; 70 import static org.onosproject.net.LinkKey.linkKey;
76 import static org.onosproject.net.intent.IntentState.INSTALLED; 71 import static org.onosproject.net.intent.IntentState.INSTALLED;
77 import static org.onosproject.net.intent.IntentState.INSTALLING; 72 import static org.onosproject.net.intent.IntentState.INSTALLING;
78 import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED; 73 import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
79 import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED; 74 import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED;
75 +import static org.onosproject.net.resource.ResourceEvent.Type.RESOURCE_ADDED;
80 import static org.slf4j.LoggerFactory.getLogger; 76 import static org.slf4j.LoggerFactory.getLogger;
81 77
82 /** 78 /**
...@@ -86,14 +82,16 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -86,14 +82,16 @@ import static org.slf4j.LoggerFactory.getLogger;
86 @Component(immediate = true) 82 @Component(immediate = true)
87 @Service 83 @Service
88 public class ObjectiveTracker implements ObjectiveTrackerService { 84 public class ObjectiveTracker implements ObjectiveTrackerService {
89 -
90 private final Logger log = getLogger(getClass()); 85 private final Logger log = getLogger(getClass());
91 86
87 + //TODO make this configurable via component config
88 + private static final long RECOMPILE_ALL_DELAY = 25; //ms
89 +
92 private final SetMultimap<LinkKey, Key> intentsByLink = 90 private final SetMultimap<LinkKey, Key> intentsByLink =
93 //TODO this could be slow as a point of synchronization 91 //TODO this could be slow as a point of synchronization
94 synchronizedSetMultimap(HashMultimap.<LinkKey, Key>create()); 92 synchronizedSetMultimap(HashMultimap.<LinkKey, Key>create());
95 93
96 - private final SetMultimap<ElementId, Key> intentsByDevice = 94 + private final SetMultimap<ElementId, Key> intentsByElement =
97 synchronizedSetMultimap(HashMultimap.<ElementId, Key>create()); 95 synchronizedSetMultimap(HashMultimap.<ElementId, Key>create());
98 96
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
...@@ -109,31 +107,28 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -109,31 +107,28 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
109 protected HostService hostService; 107 protected HostService hostService;
110 108
111 @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, 109 @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY,
112 - policy = ReferencePolicy.DYNAMIC) 110 + policy = ReferencePolicy.DYNAMIC)
113 protected IntentService intentService; 111 protected IntentService intentService;
114 112
115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 protected IntentPartitionService partitionService; 114 protected IntentPartitionService partitionService;
117 115
118 - private ExecutorService executorService = 116 + private final Timer timer = new Timer("onos/intent-objective-tracker", true);
119 - newSingleThreadExecutor(groupedThreads("onos/intent", "objectivetracker", log)); 117 + private final Accumulator<WorkMessage> workMessageAccumulator = new InternalWorkAccumulator();
120 - private ScheduledExecutorService executor = Executors
121 - .newScheduledThreadPool(1);
122 118
123 private TopologyListener listener = new InternalTopologyListener(); 119 private TopologyListener listener = new InternalTopologyListener();
124 private ResourceListener resourceListener = new InternalResourceListener(); 120 private ResourceListener resourceListener = new InternalResourceListener();
125 - private DeviceListener deviceListener = new InternalDeviceListener();
126 private HostListener hostListener = new InternalHostListener(); 121 private HostListener hostListener = new InternalHostListener();
127 private IntentPartitionEventListener partitionListener = new InternalPartitionListener(); 122 private IntentPartitionEventListener partitionListener = new InternalPartitionListener();
128 private TopologyChangeDelegate delegate; 123 private TopologyChangeDelegate delegate;
129 124
130 protected final AtomicBoolean updateScheduled = new AtomicBoolean(false); 125 protected final AtomicBoolean updateScheduled = new AtomicBoolean(false);
126 + protected final AtomicBoolean recompileAllScheduled = new AtomicBoolean(false);
131 127
132 @Activate 128 @Activate
133 public void activate() { 129 public void activate() {
134 topologyService.addListener(listener); 130 topologyService.addListener(listener);
135 resourceService.addListener(resourceListener); 131 resourceService.addListener(resourceListener);
136 - deviceService.addListener(deviceListener);
137 hostService.addListener(hostListener); 132 hostService.addListener(hostListener);
138 partitionService.addListener(partitionListener); 133 partitionService.addListener(partitionListener);
139 log.info("Started"); 134 log.info("Started");
...@@ -143,7 +138,6 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -143,7 +138,6 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
143 public void deactivate() { 138 public void deactivate() {
144 topologyService.removeListener(listener); 139 topologyService.removeListener(listener);
145 resourceService.removeListener(resourceListener); 140 resourceService.removeListener(resourceListener);
146 - deviceService.removeListener(deviceListener);
147 hostService.removeListener(hostListener); 141 hostService.removeListener(hostListener);
148 partitionService.removeListener(partitionListener); 142 partitionService.removeListener(partitionListener);
149 log.info("Stopped"); 143 log.info("Stopped");
...@@ -153,7 +147,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -153,7 +147,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
153 if (intentService == null) { 147 if (intentService == null) {
154 intentService = service; 148 intentService = service;
155 } 149 }
156 - } 150 + }
157 151
158 protected void unbindIntentService(IntentService service) { 152 protected void unbindIntentService(IntentService service) {
159 if (intentService == service) { 153 if (intentService == service) {
...@@ -182,7 +176,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -182,7 +176,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
182 if (resource instanceof Link) { 176 if (resource instanceof Link) {
183 intentsByLink.put(linkKey((Link) resource), intentKey); 177 intentsByLink.put(linkKey((Link) resource), intentKey);
184 } else if (resource instanceof ElementId) { 178 } else if (resource instanceof ElementId) {
185 - intentsByDevice.put((ElementId) resource, intentKey); 179 + intentsByElement.put((ElementId) resource, intentKey);
186 } 180 }
187 } 181 }
188 } 182 }
...@@ -194,7 +188,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -194,7 +188,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
194 if (resource instanceof Link) { 188 if (resource instanceof Link) {
195 intentsByLink.remove(linkKey((Link) resource), intentKey); 189 intentsByLink.remove(linkKey((Link) resource), intentKey);
196 } else if (resource instanceof ElementId) { 190 } else if (resource instanceof ElementId) {
197 - intentsByDevice.remove(resource, intentKey); 191 + intentsByElement.remove(resource, intentKey);
198 } 192 }
199 } 193 }
200 } 194 }
...@@ -209,18 +203,18 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -209,18 +203,18 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
209 Intent intent = intentData.intent(); 203 Intent intent = intentData.intent();
210 boolean isLocal = intentService.isLocal(key); 204 boolean isLocal = intentService.isLocal(key);
211 boolean isInstalled = intentData.state() == INSTALLING || 205 boolean isInstalled = intentData.state() == INSTALLING ||
212 - intentData.state() == INSTALLED; 206 + intentData.state() == INSTALLED;
213 List<Intent> installables = intentData.installables(); 207 List<Intent> installables = intentData.installables();
214 208
215 if (log.isTraceEnabled()) { 209 if (log.isTraceEnabled()) {
216 log.trace("intent {}, old: {}, new: {}, installableCount: {}, resourceCount: {}", 210 log.trace("intent {}, old: {}, new: {}, installableCount: {}, resourceCount: {}",
217 key, 211 key,
218 - intentsByDevice.values().contains(key), 212 + intentsByElement.values().contains(key),
219 isLocal && isInstalled, 213 isLocal && isInstalled,
220 installables.size(), 214 installables.size(),
221 intent.resources().size() + 215 intent.resources().size() +
222 - installables.stream() 216 + installables.stream()
223 - .mapToLong(i -> i.resources().size()).sum()); 217 + .mapToLong(i -> i.resources().size()).sum());
224 } 218 }
225 219
226 if (isNullOrEmpty(installables) && intentData.state() == INSTALLED) { 220 if (isNullOrEmpty(installables) && intentData.state() == INSTALLED) {
...@@ -247,52 +241,39 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -247,52 +241,39 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
247 private class InternalTopologyListener implements TopologyListener { 241 private class InternalTopologyListener implements TopologyListener {
248 @Override 242 @Override
249 public void event(TopologyEvent event) { 243 public void event(TopologyEvent event) {
250 - executorService.execute(new TopologyChangeHandler(event)); 244 + boolean recompileAllFailedIntents = false;
251 - }
252 - }
253 -
254 - // Re-dispatcher of topology change events.
255 - private class TopologyChangeHandler implements Runnable {
256 -
257 - private final TopologyEvent event;
258 -
259 - TopologyChangeHandler(TopologyEvent event) {
260 - this.event = event;
261 - }
262 -
263 - @Override
264 - public void run() {
265 - // If there is no delegate, why bother? Just bail.
266 - if (delegate == null) {
267 - return;
268 - }
269 245
270 if (event.reasons() == null || event.reasons().isEmpty()) { 246 if (event.reasons() == null || event.reasons().isEmpty()) {
271 - delegate.triggerCompile(Collections.emptySet(), true); 247 + recompileAllFailedIntents = true;
272 248
273 } else { 249 } else {
274 - Set<Key> intentsToRecompile = new HashSet<>();
275 - boolean dontRecompileAllFailedIntents = true;
276 -
277 // Scan through the list of reasons and keep accruing all 250 // Scan through the list of reasons and keep accruing all
278 // intents that need to be recompiled. 251 // intents that need to be recompiled.
279 for (Event reason : event.reasons()) { 252 for (Event reason : event.reasons()) {
253 + WorkMessage wi = new WorkMessage();
280 if (reason instanceof LinkEvent) { 254 if (reason instanceof LinkEvent) {
281 LinkEvent linkEvent = (LinkEvent) reason; 255 LinkEvent linkEvent = (LinkEvent) reason;
282 - final LinkKey linkKey = linkKey(linkEvent.subject()); 256 + wi.linkKey = linkKey(linkEvent.subject());
283 - synchronized (intentsByLink) { 257 + recompileAllFailedIntents |=
284 - Set<Key> intentKeys = intentsByLink.get(linkKey); 258 + !(linkEvent.type() == LINK_REMOVED ||
285 - log.debug("recompile triggered by LinkEvent {} ({}) for {}", 259 + (linkEvent.type() == LINK_UPDATED &&
286 - linkKey, linkEvent.type(), intentKeys); 260 + linkEvent.subject().isDurable()));
287 - intentsToRecompile.addAll(intentKeys); 261 + } else if (reason instanceof DeviceEvent) {
288 - } 262 + DeviceEvent deviceEvent = (DeviceEvent) reason;
289 - dontRecompileAllFailedIntents = dontRecompileAllFailedIntents && 263 + wi.elementId = deviceEvent.subject().id();
290 - (linkEvent.type() == LINK_REMOVED || 264 + recompileAllFailedIntents |=
291 - (linkEvent.type() == LINK_UPDATED && 265 + (deviceEvent.type() == DeviceEvent.Type.DEVICE_ADDED ||
292 - linkEvent.subject().isDurable())); 266 + deviceEvent.type() == DeviceEvent.Type.DEVICE_UPDATED ||
267 + deviceEvent.isAvailable().orElse(false));
268 + } else {
269 + continue;
293 } 270 }
271 + workMessageAccumulator.add(wi);
294 } 272 }
295 - delegate.triggerCompile(intentsToRecompile, !dontRecompileAllFailedIntents); 273 + }
274 +
275 + if (recompileAllFailedIntents) {
276 + scheduleRecompileAll();
296 } 277 }
297 } 278 }
298 } 279 }
...@@ -300,79 +281,16 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -300,79 +281,16 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
300 private class InternalResourceListener implements ResourceListener { 281 private class InternalResourceListener implements ResourceListener {
301 @Override 282 @Override
302 public void event(ResourceEvent event) { 283 public void event(ResourceEvent event) {
303 - if (event.subject().isSubTypeOf(PortNumber.class)) { 284 + if (event.type() == RESOURCE_ADDED &&
304 - executorService.execute(() -> { 285 + event.subject().isSubTypeOf(PortNumber.class)) {
305 - if (delegate == null) { 286 + scheduleRecompileAll();
306 - return;
307 - }
308 -
309 - delegate.triggerCompile(Collections.emptySet(), true);
310 - });
311 } 287 }
288 + //TODO we should probably track resources and trigger removal
312 } 289 }
313 } 290 }
314 291
315 //TODO consider adding flow rule event tracking 292 //TODO consider adding flow rule event tracking
316 293
317 - /*
318 - * Re-dispatcher of device and host events.
319 - */
320 - private class DeviceAvailabilityHandler implements Runnable {
321 -
322 - private final ElementId id;
323 - private final boolean available;
324 -
325 - DeviceAvailabilityHandler(ElementId id, boolean available) {
326 - this.id = checkNotNull(id);
327 - this.available = available;
328 - }
329 -
330 - @Override
331 - public void run() {
332 - // If there is no delegate, why bother? Just bail.
333 - if (delegate == null) {
334 - return;
335 - }
336 -
337 - // TODO should we recompile on available==true?
338 -
339 - final ImmutableSet<Key> snapshot;
340 - synchronized (intentsByDevice) {
341 - snapshot = ImmutableSet.copyOf(intentsByDevice.get(id));
342 - }
343 - delegate.triggerCompile(snapshot, available);
344 - }
345 - }
346 -
347 -
348 - private class InternalDeviceListener implements DeviceListener {
349 - @Override
350 - public void event(DeviceEvent event) {
351 - DeviceEvent.Type type = event.type();
352 - switch (type) {
353 - case DEVICE_ADDED:
354 - case DEVICE_AVAILABILITY_CHANGED:
355 - case DEVICE_REMOVED:
356 - case DEVICE_SUSPENDED:
357 - case DEVICE_UPDATED:
358 - DeviceId id = event.subject().id();
359 - // TODO we need to check whether AVAILABILITY_CHANGED means up or down
360 - boolean available = (type == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
361 - type == DeviceEvent.Type.DEVICE_ADDED ||
362 - type == DeviceEvent.Type.DEVICE_UPDATED);
363 - executorService.execute(new DeviceAvailabilityHandler(id, available));
364 - break;
365 - case PORT_ADDED:
366 - case PORT_REMOVED:
367 - case PORT_UPDATED:
368 - case PORT_STATS_UPDATED:
369 - default:
370 - // Don't handle port events for now
371 - break;
372 - }
373 - }
374 - }
375 -
376 private class InternalHostListener implements HostListener { 294 private class InternalHostListener implements HostListener {
377 @Override 295 @Override
378 public void event(HostEvent event) { 296 public void event(HostEvent event) {
...@@ -381,7 +299,10 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -381,7 +299,10 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
381 case HOST_ADDED: 299 case HOST_ADDED:
382 case HOST_MOVED: 300 case HOST_MOVED:
383 case HOST_REMOVED: 301 case HOST_REMOVED:
384 - executorService.execute(new DeviceAvailabilityHandler(id, false)); 302 + WorkMessage wi = new WorkMessage();
303 + wi.elementId = id;
304 + workMessageAccumulator.add(wi);
305 + scheduleRecompileAll();
385 break; 306 break;
386 case HOST_UPDATED: 307 case HOST_UPDATED:
387 default: 308 default:
...@@ -413,7 +334,31 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -413,7 +334,31 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
413 334
414 private void scheduleIntentUpdate(int afterDelaySec) { 335 private void scheduleIntentUpdate(int afterDelaySec) {
415 if (updateScheduled.compareAndSet(false, true)) { 336 if (updateScheduled.compareAndSet(false, true)) {
416 - executor.schedule(this::doIntentUpdate, afterDelaySec, TimeUnit.SECONDS); 337 + timer.schedule(new TimerTask() {
338 + @Override
339 + public void run() {
340 + ObjectiveTracker.this.doIntentUpdate();
341 + }
342 + }, afterDelaySec * 1_000);
343 + }
344 + }
345 +
346 + private void doRecompileAll() {
347 + recompileAllScheduled.set(false);
348 + if (delegate != null) {
349 + delegate.triggerCompile(Collections.emptySet(), true);
350 + }
351 + }
352 +
353 + private void scheduleRecompileAll() {
354 + if (recompileAllScheduled.compareAndSet(false, true)) {
355 + timer.schedule(new TimerTask() {
356 + @Override
357 + public void run() {
358 + ObjectiveTracker.this.doRecompileAll();
359 + }
360 + }, RECOMPILE_ALL_DELAY);
361 +
417 } 362 }
418 } 363 }
419 364
...@@ -424,4 +369,47 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -424,4 +369,47 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
424 scheduleIntentUpdate(1); 369 scheduleIntentUpdate(1);
425 } 370 }
426 } 371 }
372 +
373 + private static class WorkMessage {
374 + ElementId elementId;
375 + LinkKey linkKey;
376 + }
377 +
378 + private class InternalWorkAccumulator extends AbstractAccumulator<WorkMessage> {
379 + private static final int MAX_WORK = 100_000;
380 + private static final int MAX_WORK_TIME = 500;
381 + private static final int MAX_WORK_IDLE_TIME = 20;
382 +
383 + InternalWorkAccumulator() {
384 + super(timer, MAX_WORK, MAX_WORK_TIME, MAX_WORK_IDLE_TIME);
385 + }
386 +
387 + @Override
388 + public void processItems(List<WorkMessage> items) {
389 + // If there is no delegate, why bother? Just bail.
390 + if (delegate == null) {
391 + return;
392 + }
393 +
394 + Set<Key> keys = Sets.newHashSet();
395 +
396 + items.forEach(wi -> {
397 + if (wi.elementId != null) {
398 + synchronized (intentsByElement) {
399 + keys.addAll(intentsByElement.get(wi.elementId));
400 + }
401 + }
402 +
403 + if (wi.linkKey != null) {
404 + synchronized (intentsByLink) {
405 + keys.addAll(intentsByLink.get(wi.linkKey));
406 + }
407 + }
408 + });
409 +
410 + if (!keys.isEmpty()) {
411 + delegate.triggerCompile(keys, false);
412 + }
413 + }
414 + }
427 } 415 }
......
...@@ -15,12 +15,8 @@ ...@@ -15,12 +15,8 @@
15 */ 15 */
16 package org.onosproject.net.intent.impl; 16 package org.onosproject.net.intent.impl;
17 17
18 -import java.util.Collection; 18 +import com.google.common.collect.ImmutableSet;
19 -import java.util.LinkedList; 19 +import com.google.common.collect.Lists;
20 -import java.util.List;
21 -import java.util.concurrent.CountDownLatch;
22 -import java.util.concurrent.TimeUnit;
23 -
24 import org.junit.After; 20 import org.junit.After;
25 import org.junit.Before; 21 import org.junit.Before;
26 import org.junit.Test; 22 import org.junit.Test;
...@@ -30,11 +26,13 @@ import org.onosproject.core.IdGenerator; ...@@ -30,11 +26,13 @@ import org.onosproject.core.IdGenerator;
30 import org.onosproject.event.Event; 26 import org.onosproject.event.Event;
31 import org.onosproject.net.Device; 27 import org.onosproject.net.Device;
32 import org.onosproject.net.DeviceId; 28 import org.onosproject.net.DeviceId;
29 +import org.onosproject.net.Host;
33 import org.onosproject.net.Link; 30 import org.onosproject.net.Link;
34 import org.onosproject.net.NetworkResource; 31 import org.onosproject.net.NetworkResource;
35 import org.onosproject.net.PortNumber; 32 import org.onosproject.net.PortNumber;
36 import org.onosproject.net.device.DeviceEvent; 33 import org.onosproject.net.device.DeviceEvent;
37 -import org.onosproject.net.device.DeviceListener; 34 +import org.onosproject.net.host.HostEvent;
35 +import org.onosproject.net.host.HostListener;
38 import org.onosproject.net.intent.Intent; 36 import org.onosproject.net.intent.Intent;
39 import org.onosproject.net.intent.Key; 37 import org.onosproject.net.intent.Key;
40 import org.onosproject.net.intent.MockIdGenerator; 38 import org.onosproject.net.intent.MockIdGenerator;
...@@ -46,18 +44,17 @@ import org.onosproject.net.topology.Topology; ...@@ -46,18 +44,17 @@ import org.onosproject.net.topology.Topology;
46 import org.onosproject.net.topology.TopologyEvent; 44 import org.onosproject.net.topology.TopologyEvent;
47 import org.onosproject.net.topology.TopologyListener; 45 import org.onosproject.net.topology.TopologyListener;
48 46
49 -import com.google.common.collect.ImmutableSet; 47 +import java.util.Collection;
50 -import com.google.common.collect.Lists; 48 +import java.util.LinkedList;
49 +import java.util.List;
50 +import java.util.concurrent.CountDownLatch;
51 +import java.util.concurrent.TimeUnit;
51 52
52 import static org.easymock.EasyMock.createMock; 53 import static org.easymock.EasyMock.createMock;
53 import static org.hamcrest.MatcherAssert.assertThat; 54 import static org.hamcrest.MatcherAssert.assertThat;
54 -import static org.hamcrest.Matchers.equalTo; 55 +import static org.hamcrest.Matchers.*;
55 -import static org.hamcrest.Matchers.hasSize; 56 +import static org.onosproject.net.NetTestTools.*;
56 -import static org.hamcrest.Matchers.is; 57 +import static org.onosproject.net.resource.ResourceEvent.Type.RESOURCE_ADDED;
57 -import static org.onosproject.net.resource.ResourceEvent.Type.*;
58 -import static org.onosproject.net.NetTestTools.APP_ID;
59 -import static org.onosproject.net.NetTestTools.device;
60 -import static org.onosproject.net.NetTestTools.link;
61 58
62 /** 59 /**
63 * Tests for the objective tracker. 60 * Tests for the objective tracker.
...@@ -69,7 +66,7 @@ public class ObjectiveTrackerTest { ...@@ -69,7 +66,7 @@ public class ObjectiveTrackerTest {
69 private TestTopologyChangeDelegate delegate; 66 private TestTopologyChangeDelegate delegate;
70 private List<Event> reasons; 67 private List<Event> reasons;
71 private TopologyListener listener; 68 private TopologyListener listener;
72 - private DeviceListener deviceListener; 69 + private HostListener hostListener;
73 private ResourceListener resourceListener; 70 private ResourceListener resourceListener;
74 private IdGenerator mockGenerator; 71 private IdGenerator mockGenerator;
75 72
...@@ -86,7 +83,7 @@ public class ObjectiveTrackerTest { ...@@ -86,7 +83,7 @@ public class ObjectiveTrackerTest {
86 tracker.setDelegate(delegate); 83 tracker.setDelegate(delegate);
87 reasons = new LinkedList<>(); 84 reasons = new LinkedList<>();
88 listener = TestUtils.getField(tracker, "listener"); 85 listener = TestUtils.getField(tracker, "listener");
89 - deviceListener = TestUtils.getField(tracker, "deviceListener"); 86 + hostListener = TestUtils.getField(tracker, "hostListener");
90 resourceListener = TestUtils.getField(tracker, "resourceListener"); 87 resourceListener = TestUtils.getField(tracker, "resourceListener");
91 mockGenerator = new MockIdGenerator(); 88 mockGenerator = new MockIdGenerator();
92 Intent.bindIdGenerator(mockGenerator); 89 Intent.bindIdGenerator(mockGenerator);
...@@ -107,16 +104,14 @@ public class ObjectiveTrackerTest { ...@@ -107,16 +104,14 @@ public class ObjectiveTrackerTest {
107 * to be generated. 104 * to be generated.
108 */ 105 */
109 static class TestTopologyChangeDelegate implements TopologyChangeDelegate { 106 static class TestTopologyChangeDelegate implements TopologyChangeDelegate {
110 -
111 CountDownLatch latch = new CountDownLatch(1); 107 CountDownLatch latch = new CountDownLatch(1);
112 - List<Key> intentIdsFromEvent; 108 + List<Key> intentIdsFromEvent = Lists.newArrayList();
113 - boolean compileAllFailedFromEvent; 109 + boolean compileAllFailedFromEvent = false;
114 110
115 @Override 111 @Override
116 - public void triggerCompile(Iterable<Key> intentKeys, 112 + public void triggerCompile(Iterable<Key> intentKeys, boolean compileAllFailed) {
117 - boolean compileAllFailed) { 113 + intentKeys.forEach(intentIdsFromEvent::add);
118 - intentIdsFromEvent = Lists.newArrayList(intentKeys); 114 + compileAllFailedFromEvent |= compileAllFailed;
119 - compileAllFailedFromEvent = compileAllFailed;
120 latch.countDown(); 115 latch.countDown();
121 } 116 }
122 } 117 }
...@@ -128,16 +123,10 @@ public class ObjectiveTrackerTest { ...@@ -128,16 +123,10 @@ public class ObjectiveTrackerTest {
128 */ 123 */
129 @Test 124 @Test
130 public void testEventNoReasons() throws InterruptedException { 125 public void testEventNoReasons() throws InterruptedException {
131 - final TopologyEvent event = new TopologyEvent( 126 + TopologyEvent event = new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, topology, null);
132 - TopologyEvent.Type.TOPOLOGY_CHANGED,
133 - topology,
134 - null);
135 -
136 listener.event(event); 127 listener.event(event);
137 - assertThat(
138 - delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
139 - is(true));
140 128
129 + assertThat(delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS), is(true));
141 assertThat(delegate.intentIdsFromEvent, hasSize(0)); 130 assertThat(delegate.intentIdsFromEvent, hasSize(0));
142 assertThat(delegate.compileAllFailedFromEvent, is(true)); 131 assertThat(delegate.compileAllFailedFromEvent, is(true));
143 } 132 }
...@@ -150,20 +139,15 @@ public class ObjectiveTrackerTest { ...@@ -150,20 +139,15 @@ public class ObjectiveTrackerTest {
150 */ 139 */
151 @Test 140 @Test
152 public void testEventLinkDownNoMatches() throws InterruptedException { 141 public void testEventLinkDownNoMatches() throws InterruptedException {
153 - final Link link = link("src", 1, "dst", 2); 142 + Link link = link("src", 1, "dst", 2);
154 - final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link); 143 + LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link);
155 reasons.add(linkEvent); 144 reasons.add(linkEvent);
156 145
157 - final TopologyEvent event = new TopologyEvent( 146 + TopologyEvent event = new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, topology, reasons);
158 - TopologyEvent.Type.TOPOLOGY_CHANGED,
159 - topology,
160 - reasons);
161 -
162 listener.event(event); 147 listener.event(event);
163 - assertThat(
164 - delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
165 - is(true));
166 148
149 + // we expect no message, latch should never fire
150 + assertThat(delegate.latch.await(25, TimeUnit.MILLISECONDS), is(false));
167 assertThat(delegate.intentIdsFromEvent, hasSize(0)); 151 assertThat(delegate.intentIdsFromEvent, hasSize(0));
168 assertThat(delegate.compileAllFailedFromEvent, is(false)); 152 assertThat(delegate.compileAllFailedFromEvent, is(false));
169 } 153 }
...@@ -175,20 +159,14 @@ public class ObjectiveTrackerTest { ...@@ -175,20 +159,14 @@ public class ObjectiveTrackerTest {
175 */ 159 */
176 @Test 160 @Test
177 public void testEventLinkAdded() throws InterruptedException { 161 public void testEventLinkAdded() throws InterruptedException {
178 - final Link link = link("src", 1, "dst", 2); 162 + Link link = link("src", 1, "dst", 2);
179 - final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_ADDED, link); 163 + LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_ADDED, link);
180 reasons.add(linkEvent); 164 reasons.add(linkEvent);
181 165
182 - final TopologyEvent event = new TopologyEvent( 166 + TopologyEvent event = new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, topology, reasons);
183 - TopologyEvent.Type.TOPOLOGY_CHANGED,
184 - topology,
185 - reasons);
186 167
187 listener.event(event); 168 listener.event(event);
188 - assertThat( 169 + assertThat(delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS), is(true));
189 - delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
190 - is(true));
191 -
192 assertThat(delegate.intentIdsFromEvent, hasSize(0)); 170 assertThat(delegate.intentIdsFromEvent, hasSize(0));
193 assertThat(delegate.compileAllFailedFromEvent, is(true)); 171 assertThat(delegate.compileAllFailedFromEvent, is(true));
194 } 172 }
...@@ -200,24 +178,18 @@ public class ObjectiveTrackerTest { ...@@ -200,24 +178,18 @@ public class ObjectiveTrackerTest {
200 */ 178 */
201 @Test 179 @Test
202 public void testEventLinkDownMatch() throws Exception { 180 public void testEventLinkDownMatch() throws Exception {
203 - final Link link = link("src", 1, "dst", 2); 181 + Link link = link("src", 1, "dst", 2);
204 - final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link); 182 + LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link);
205 reasons.add(linkEvent); 183 reasons.add(linkEvent);
206 184
207 - final TopologyEvent event = new TopologyEvent( 185 + TopologyEvent event = new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, topology, reasons);
208 - TopologyEvent.Type.TOPOLOGY_CHANGED,
209 - topology,
210 - reasons);
211 186
212 - final Key key = Key.of(0x333L, APP_ID); 187 + Key key = Key.of(0x333L, APP_ID);
213 Collection<NetworkResource> resources = ImmutableSet.of(link); 188 Collection<NetworkResource> resources = ImmutableSet.of(link);
214 tracker.addTrackedResources(key, resources); 189 tracker.addTrackedResources(key, resources);
215 190
216 listener.event(event); 191 listener.event(event);
217 - assertThat( 192 + assertThat(delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS), is(true));
218 - delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
219 - is(true));
220 -
221 assertThat(delegate.intentIdsFromEvent, hasSize(1)); 193 assertThat(delegate.intentIdsFromEvent, hasSize(1));
222 assertThat(delegate.compileAllFailedFromEvent, is(false)); 194 assertThat(delegate.compileAllFailedFromEvent, is(false));
223 assertThat(delegate.intentIdsFromEvent.get(0).toString(), 195 assertThat(delegate.intentIdsFromEvent.get(0).toString(),
...@@ -232,13 +204,11 @@ public class ObjectiveTrackerTest { ...@@ -232,13 +204,11 @@ public class ObjectiveTrackerTest {
232 @Test 204 @Test
233 public void testResourceEvent() throws Exception { 205 public void testResourceEvent() throws Exception {
234 ResourceEvent event = new ResourceEvent(RESOURCE_ADDED, 206 ResourceEvent event = new ResourceEvent(RESOURCE_ADDED,
235 - Resources.discrete(DeviceId.deviceId("a"), PortNumber.portNumber(1)).resource()); 207 + Resources.discrete(DeviceId.deviceId("a"),
208 + PortNumber.portNumber(1)).resource());
236 resourceListener.event(event); 209 resourceListener.event(event);
237 210
238 - assertThat( 211 + assertThat(delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS), is(true));
239 - delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
240 - is(true));
241 -
242 assertThat(delegate.intentIdsFromEvent, hasSize(0)); 212 assertThat(delegate.intentIdsFromEvent, hasSize(0));
243 assertThat(delegate.compileAllFailedFromEvent, is(true)); 213 assertThat(delegate.compileAllFailedFromEvent, is(true));
244 } 214 }
...@@ -251,25 +221,27 @@ public class ObjectiveTrackerTest { ...@@ -251,25 +221,27 @@ public class ObjectiveTrackerTest {
251 221
252 @Test 222 @Test
253 public void testEventHostAvailableMatch() throws Exception { 223 public void testEventHostAvailableMatch() throws Exception {
254 - final Device host = device("host1"); 224 + // we will expect 2 delegate calls
225 + delegate.latch = new CountDownLatch(2);
255 226
256 - final DeviceEvent deviceEvent = 227 + Device host = device("host1");
257 - new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, host); 228 + DeviceEvent deviceEvent = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, host);
258 reasons.add(deviceEvent); 229 reasons.add(deviceEvent);
259 230
260 - final Key key = Key.of(0x333L, APP_ID); 231 + Key key = Key.of(0x333L, APP_ID);
261 Collection<NetworkResource> resources = ImmutableSet.of(host.id()); 232 Collection<NetworkResource> resources = ImmutableSet.of(host.id());
262 tracker.addTrackedResources(key, resources); 233 tracker.addTrackedResources(key, resources);
263 234
264 - deviceListener.event(deviceEvent); 235 + reasons.add(deviceEvent);
265 - assertThat( 236 +
266 - delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS), 237 + TopologyEvent event = new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, topology, reasons);
267 - is(true));
268 238
239 + listener.event(event);
240 + assertThat(delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS), is(true));
269 assertThat(delegate.intentIdsFromEvent, hasSize(1)); 241 assertThat(delegate.intentIdsFromEvent, hasSize(1));
270 assertThat(delegate.compileAllFailedFromEvent, is(true)); 242 assertThat(delegate.compileAllFailedFromEvent, is(true));
271 assertThat(delegate.intentIdsFromEvent.get(0).toString(), 243 assertThat(delegate.intentIdsFromEvent.get(0).toString(),
272 - equalTo("0x333")); 244 + equalTo("0x333"));
273 } 245 }
274 246
275 /** 247 /**
...@@ -280,25 +252,21 @@ public class ObjectiveTrackerTest { ...@@ -280,25 +252,21 @@ public class ObjectiveTrackerTest {
280 252
281 @Test 253 @Test
282 public void testEventHostUnavailableMatch() throws Exception { 254 public void testEventHostUnavailableMatch() throws Exception {
283 - final Device host = device("host1"); 255 + Device host = device("host1");
284 - 256 + DeviceEvent deviceEvent = new DeviceEvent(DeviceEvent.Type.DEVICE_REMOVED, host);
285 - final DeviceEvent deviceEvent =
286 - new DeviceEvent(DeviceEvent.Type.DEVICE_REMOVED, host);
287 reasons.add(deviceEvent); 257 reasons.add(deviceEvent);
288 258
289 - final Key key = Key.of(0x333L, APP_ID); 259 + Key key = Key.of(0x333L, APP_ID);
290 Collection<NetworkResource> resources = ImmutableSet.of(host.id()); 260 Collection<NetworkResource> resources = ImmutableSet.of(host.id());
291 tracker.addTrackedResources(key, resources); 261 tracker.addTrackedResources(key, resources);
292 262
293 - deviceListener.event(deviceEvent); 263 + TopologyEvent event = new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, topology, reasons);
294 - assertThat(
295 - delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
296 - is(true));
297 264
265 + listener.event(event);
266 + assertThat(delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS), is(true));
298 assertThat(delegate.intentIdsFromEvent, hasSize(1)); 267 assertThat(delegate.intentIdsFromEvent, hasSize(1));
299 assertThat(delegate.compileAllFailedFromEvent, is(false)); 268 assertThat(delegate.compileAllFailedFromEvent, is(false));
300 - assertThat(delegate.intentIdsFromEvent.get(0).toString(), 269 + assertThat(delegate.intentIdsFromEvent.get(0).toString(), equalTo("0x333"));
301 - equalTo("0x333"));
302 } 270 }
303 271
304 /** 272 /**
...@@ -309,20 +277,12 @@ public class ObjectiveTrackerTest { ...@@ -309,20 +277,12 @@ public class ObjectiveTrackerTest {
309 277
310 @Test 278 @Test
311 public void testEventHostAvailableNoMatch() throws Exception { 279 public void testEventHostAvailableNoMatch() throws Exception {
312 - final Device host = device("host1"); 280 + Host host = host("00:11:22:33:44:55/6", "device1");
313 - 281 + HostEvent hostEvent = new HostEvent(HostEvent.Type.HOST_ADDED, host);
314 - final DeviceEvent deviceEvent = 282 + hostListener.event(hostEvent);
315 - new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, host); 283 + assertThat(delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS), is(true));
316 - reasons.add(deviceEvent);
317 -
318 - deviceListener.event(deviceEvent);
319 - assertThat(
320 - delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
321 - is(true));
322 -
323 assertThat(delegate.intentIdsFromEvent, hasSize(0)); 284 assertThat(delegate.intentIdsFromEvent, hasSize(0));
324 assertThat(delegate.compileAllFailedFromEvent, is(true)); 285 assertThat(delegate.compileAllFailedFromEvent, is(true));
325 } 286 }
326 287
327 -
328 } 288 }
......
...@@ -444,7 +444,7 @@ public class GossipDeviceStore ...@@ -444,7 +444,7 @@ public class GossipDeviceStore
444 boolean wasOnline = availableDevices.contains(newDevice.id()); 444 boolean wasOnline = availableDevices.contains(newDevice.id());
445 markOnline(newDevice.id(), newTimestamp); 445 markOnline(newDevice.id(), newTimestamp);
446 if (!wasOnline) { 446 if (!wasOnline) {
447 - notifyDelegateIfNotNull(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, newDevice, null)); 447 + notifyDelegateIfNotNull(new DeviceEvent(newDevice, true));
448 } 448 }
449 } 449 }
450 return event; 450 return event;
...@@ -487,7 +487,7 @@ public class GossipDeviceStore ...@@ -487,7 +487,7 @@ public class GossipDeviceStore
487 } 487 }
488 boolean removed = availableDevices.remove(deviceId); 488 boolean removed = availableDevices.remove(deviceId);
489 if (removed) { 489 if (removed) {
490 - return new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device, null); 490 + return new DeviceEvent(device, false);
491 } 491 }
492 return null; 492 return null;
493 } 493 }
......