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
Showing
4 changed files
with
213 additions
and
237 deletions
... | @@ -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 | } | ... | ... |
-
Please register or login to post a comment