Committed by
Jonathan Hart
Lazily populate Pipeliner cache
Change-Id: Ibbb9312b47c2c61df9ed15370b46fb07a8c7a16c
Showing
2 changed files
with
27 additions
and
81 deletions
... | @@ -27,9 +27,6 @@ import org.onlab.osgi.DefaultServiceDirectory; | ... | @@ -27,9 +27,6 @@ import org.onlab.osgi.DefaultServiceDirectory; |
27 | import org.onlab.osgi.ServiceDirectory; | 27 | import org.onlab.osgi.ServiceDirectory; |
28 | import org.onlab.util.ItemNotFoundException; | 28 | import org.onlab.util.ItemNotFoundException; |
29 | import org.onosproject.cluster.ClusterService; | 29 | import org.onosproject.cluster.ClusterService; |
30 | -import org.onosproject.mastership.MastershipEvent; | ||
31 | -import org.onosproject.mastership.MastershipListener; | ||
32 | -import org.onosproject.mastership.MastershipService; | ||
33 | import org.onosproject.net.DeviceId; | 30 | import org.onosproject.net.DeviceId; |
34 | import org.onosproject.net.behaviour.NextGroup; | 31 | import org.onosproject.net.behaviour.NextGroup; |
35 | import org.onosproject.net.behaviour.Pipeliner; | 32 | import org.onosproject.net.behaviour.Pipeliner; |
... | @@ -87,9 +84,6 @@ public class FlowObjectiveManager implements FlowObjectiveService { | ... | @@ -87,9 +84,6 @@ public class FlowObjectiveManager implements FlowObjectiveService { |
87 | protected DeviceService deviceService; | 84 | protected DeviceService deviceService; |
88 | 85 | ||
89 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 86 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
90 | - protected MastershipService mastershipService; | ||
91 | - | ||
92 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
93 | protected ClusterService clusterService; | 87 | protected ClusterService clusterService; |
94 | 88 | ||
95 | // Note: The following dependencies are added on behalf of the pipeline | 89 | // Note: The following dependencies are added on behalf of the pipeline |
... | @@ -116,7 +110,6 @@ public class FlowObjectiveManager implements FlowObjectiveService { | ... | @@ -116,7 +110,6 @@ public class FlowObjectiveManager implements FlowObjectiveService { |
116 | private final Map<DeviceId, Pipeliner> pipeliners = Maps.newConcurrentMap(); | 110 | private final Map<DeviceId, Pipeliner> pipeliners = Maps.newConcurrentMap(); |
117 | 111 | ||
118 | private final PipelinerContext context = new InnerPipelineContext(); | 112 | private final PipelinerContext context = new InnerPipelineContext(); |
119 | - private final MastershipListener mastershipListener = new InnerMastershipListener(); | ||
120 | private final DeviceListener deviceListener = new InnerDeviceListener(); | 113 | private final DeviceListener deviceListener = new InnerDeviceListener(); |
121 | 114 | ||
122 | protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory(); | 115 | protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory(); |
... | @@ -133,16 +126,13 @@ public class FlowObjectiveManager implements FlowObjectiveService { | ... | @@ -133,16 +126,13 @@ public class FlowObjectiveManager implements FlowObjectiveService { |
133 | protected void activate() { | 126 | protected void activate() { |
134 | executorService = newFixedThreadPool(4, groupedThreads("onos/objective-installer", "%d", log)); | 127 | executorService = newFixedThreadPool(4, groupedThreads("onos/objective-installer", "%d", log)); |
135 | flowObjectiveStore.setDelegate(delegate); | 128 | flowObjectiveStore.setDelegate(delegate); |
136 | - mastershipService.addListener(mastershipListener); | ||
137 | deviceService.addListener(deviceListener); | 129 | deviceService.addListener(deviceListener); |
138 | - deviceService.getDevices().forEach(device -> setupPipelineHandler(device.id())); | ||
139 | log.info("Started"); | 130 | log.info("Started"); |
140 | } | 131 | } |
141 | 132 | ||
142 | @Deactivate | 133 | @Deactivate |
143 | protected void deactivate() { | 134 | protected void deactivate() { |
144 | flowObjectiveStore.unsetDelegate(delegate); | 135 | flowObjectiveStore.unsetDelegate(delegate); |
145 | - mastershipService.removeListener(mastershipListener); | ||
146 | deviceService.removeListener(deviceListener); | 136 | deviceService.removeListener(deviceListener); |
147 | executorService.shutdown(); | 137 | executorService.shutdown(); |
148 | pipeliners.clear(); | 138 | pipeliners.clear(); |
... | @@ -265,13 +255,24 @@ public class FlowObjectiveManager implements FlowObjectiveService { | ... | @@ -265,13 +255,24 @@ public class FlowObjectiveManager implements FlowObjectiveService { |
265 | 255 | ||
266 | // Retrieves the device pipeline behaviour from the cache. | 256 | // Retrieves the device pipeline behaviour from the cache. |
267 | private Pipeliner getDevicePipeliner(DeviceId deviceId) { | 257 | private Pipeliner getDevicePipeliner(DeviceId deviceId) { |
268 | - return pipeliners.get(deviceId); | 258 | + return pipeliners.computeIfAbsent(deviceId, this::initPipelineHandler); |
269 | } | 259 | } |
270 | 260 | ||
271 | - private void setupPipelineHandler(DeviceId deviceId) { | 261 | + /** |
262 | + * Creates and initialize {@link Pipeliner}. | ||
263 | + * <p> | ||
264 | + * Note: Expected to be called under per-Device lock. | ||
265 | + * e.g., {@code pipeliners}' Map#compute family methods | ||
266 | + * | ||
267 | + * @param deviceId Device to initialize pipeliner | ||
268 | + * @return {@link Pipeliner} instance or null | ||
269 | + */ | ||
270 | + private Pipeliner initPipelineHandler(DeviceId deviceId) { | ||
271 | + start = now(); | ||
272 | + // ?? We never use defaultDriverService, do we still need this check? | ||
272 | if (defaultDriverService == null) { | 273 | if (defaultDriverService == null) { |
273 | // We're not ready to go to work yet. | 274 | // We're not ready to go to work yet. |
274 | - return; | 275 | + return null; |
275 | } | 276 | } |
276 | 277 | ||
277 | // Attempt to lookup the handler in the cache | 278 | // Attempt to lookup the handler in the cache |
... | @@ -286,11 +287,11 @@ public class FlowObjectiveManager implements FlowObjectiveService { | ... | @@ -286,11 +287,11 @@ public class FlowObjectiveManager implements FlowObjectiveService { |
286 | if (!handler.driver().hasBehaviour(Pipeliner.class)) { | 287 | if (!handler.driver().hasBehaviour(Pipeliner.class)) { |
287 | log.warn("Pipeline behaviour not supported for device {}", | 288 | log.warn("Pipeline behaviour not supported for device {}", |
288 | deviceId); | 289 | deviceId); |
289 | - return; | 290 | + return null; |
290 | } | 291 | } |
291 | } catch (ItemNotFoundException e) { | 292 | } catch (ItemNotFoundException e) { |
292 | log.warn("No applicable driver for device {}", deviceId); | 293 | log.warn("No applicable driver for device {}", deviceId); |
293 | - return; | 294 | + return null; |
294 | } | 295 | } |
295 | 296 | ||
296 | driverHandlers.put(deviceId, handler); | 297 | driverHandlers.put(deviceId, handler); |
... | @@ -304,28 +305,8 @@ public class FlowObjectiveManager implements FlowObjectiveService { | ... | @@ -304,28 +305,8 @@ public class FlowObjectiveManager implements FlowObjectiveService { |
304 | Pipeliner pipeliner = handler.behaviour(Pipeliner.class); | 305 | Pipeliner pipeliner = handler.behaviour(Pipeliner.class); |
305 | hbTime = now(); | 306 | hbTime = now(); |
306 | pipeliner.init(deviceId, context); | 307 | pipeliner.init(deviceId, context); |
307 | - pipeliners.put(deviceId, pipeliner); | 308 | + stopWatch(); |
308 | - } | 309 | + return pipeliner; |
309 | - | ||
310 | - // Triggers driver setup when the local node becomes a device master. | ||
311 | - private class InnerMastershipListener implements MastershipListener { | ||
312 | - @Override | ||
313 | - public void event(MastershipEvent event) { | ||
314 | - switch (event.type()) { | ||
315 | - case MASTER_CHANGED: | ||
316 | - log.debug("mastership changed on device {}", event.subject()); | ||
317 | - start = now(); | ||
318 | - if (deviceService.isAvailable(event.subject())) { | ||
319 | - setupPipelineHandler(event.subject()); | ||
320 | - } | ||
321 | - stopWatch(); | ||
322 | - break; | ||
323 | - case BACKUPS_CHANGED: | ||
324 | - break; | ||
325 | - default: | ||
326 | - break; | ||
327 | - } | ||
328 | - } | ||
329 | } | 310 | } |
330 | 311 | ||
331 | // Triggers driver setup when a device is (re)detected. | 312 | // Triggers driver setup when a device is (re)detected. |
... | @@ -337,18 +318,23 @@ public class FlowObjectiveManager implements FlowObjectiveService { | ... | @@ -337,18 +318,23 @@ public class FlowObjectiveManager implements FlowObjectiveService { |
337 | case DEVICE_AVAILABILITY_CHANGED: | 318 | case DEVICE_AVAILABILITY_CHANGED: |
338 | log.debug("Device either added or availability changed {}", | 319 | log.debug("Device either added or availability changed {}", |
339 | event.subject().id()); | 320 | event.subject().id()); |
340 | - start = now(); | ||
341 | if (deviceService.isAvailable(event.subject().id())) { | 321 | if (deviceService.isAvailable(event.subject().id())) { |
342 | log.debug("Device is now available {}", event.subject().id()); | 322 | log.debug("Device is now available {}", event.subject().id()); |
343 | - setupPipelineHandler(event.subject().id()); | 323 | + getDevicePipeliner(event.subject().id()); |
324 | + } else { | ||
325 | + log.debug("Device is no longer available {}", event.subject().id()); | ||
326 | + // evict Pipeliner cache. | ||
327 | + // User might restart Device to assign new Driver/Pipeliner | ||
328 | + // loaded afterwards. | ||
329 | + pipeliners.remove(event.subject().id()); | ||
344 | } | 330 | } |
345 | - stopWatch(); | ||
346 | break; | 331 | break; |
347 | case DEVICE_UPDATED: | 332 | case DEVICE_UPDATED: |
348 | break; | 333 | break; |
349 | case DEVICE_REMOVED: | 334 | case DEVICE_REMOVED: |
350 | - break; | ||
351 | case DEVICE_SUSPENDED: | 335 | case DEVICE_SUSPENDED: |
336 | + // evict Pipeliner cache. | ||
337 | + pipeliners.remove(event.subject().id()); | ||
352 | break; | 338 | break; |
353 | case PORT_ADDED: | 339 | case PORT_ADDED: |
354 | break; | 340 | break; | ... | ... |
... | @@ -23,9 +23,6 @@ import org.junit.Before; | ... | @@ -23,9 +23,6 @@ import org.junit.Before; |
23 | import org.junit.Test; | 23 | import org.junit.Test; |
24 | import org.onlab.junit.TestUtils; | 24 | import org.onlab.junit.TestUtils; |
25 | import org.onlab.packet.ChassisId; | 25 | import org.onlab.packet.ChassisId; |
26 | -import org.onosproject.mastership.MastershipEvent; | ||
27 | -import org.onosproject.mastership.MastershipListener; | ||
28 | -import org.onosproject.mastership.MastershipServiceAdapter; | ||
29 | import org.onosproject.net.DefaultAnnotations; | 26 | import org.onosproject.net.DefaultAnnotations; |
30 | import org.onosproject.net.DefaultDevice; | 27 | import org.onosproject.net.DefaultDevice; |
31 | import org.onosproject.net.Device; | 28 | import org.onosproject.net.Device; |
... | @@ -190,7 +187,6 @@ public class FlowObjectiveManagerTest { | ... | @@ -190,7 +187,6 @@ public class FlowObjectiveManagerTest { |
190 | public void initializeTest() { | 187 | public void initializeTest() { |
191 | manager = new FlowObjectiveManager(); | 188 | manager = new FlowObjectiveManager(); |
192 | manager.flowObjectiveStore = new TestFlowObjectiveStore(); | 189 | manager.flowObjectiveStore = new TestFlowObjectiveStore(); |
193 | - manager.mastershipService = new MastershipServiceAdapter(); | ||
194 | manager.deviceService = new TestDeviceService(); | 190 | manager.deviceService = new TestDeviceService(); |
195 | manager.defaultDriverService = new TestDriversLoader(); | 191 | manager.defaultDriverService = new TestDriversLoader(); |
196 | manager.driverService = new TestDriverService(); | 192 | manager.driverService = new TestDriverService(); |
... | @@ -377,40 +373,4 @@ public class FlowObjectiveManagerTest { | ... | @@ -377,40 +373,4 @@ public class FlowObjectiveManagerTest { |
377 | assertThat(filteringObjectives, hasSize(0)); | 373 | assertThat(filteringObjectives, hasSize(0)); |
378 | assertThat(nextObjectives, hasSize(0)); | 374 | assertThat(nextObjectives, hasSize(0)); |
379 | } | 375 | } |
380 | - | ||
381 | - /** | ||
382 | - * Tests recepit of a device mastership event. | ||
383 | - * | ||
384 | - * @throws TestUtilsException if lookup of a field fails | ||
385 | - */ | ||
386 | - @Test | ||
387 | - public void deviceMastershipEvent() throws TestUtilsException { | ||
388 | - TrafficSelector selector = DefaultTrafficSelector.emptySelector(); | ||
389 | - TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment(); | ||
390 | - | ||
391 | - MastershipEvent event = | ||
392 | - new MastershipEvent(MastershipEvent.Type.MASTER_CHANGED, id2, null); | ||
393 | - MastershipListener listener = TestUtils.getField(manager, "mastershipListener"); | ||
394 | - assertThat(listener, notNullValue()); | ||
395 | - | ||
396 | - listener.event(event); | ||
397 | - | ||
398 | - ForwardingObjective forward = | ||
399 | - DefaultForwardingObjective.builder() | ||
400 | - .fromApp(NetTestTools.APP_ID) | ||
401 | - .withFlag(ForwardingObjective.Flag.SPECIFIC) | ||
402 | - .withSelector(selector) | ||
403 | - .withTreatment(treatment) | ||
404 | - .makePermanent() | ||
405 | - .add(); | ||
406 | - manager.forward(id2, forward); | ||
407 | - | ||
408 | - // new device should have an objective now | ||
409 | - TestTools.assertAfter(RETRY_MS, () -> | ||
410 | - assertThat(forwardingObjectives, hasSize(1))); | ||
411 | - | ||
412 | - assertThat(forwardingObjectives, hasItem("of:d2")); | ||
413 | - assertThat(filteringObjectives, hasSize(0)); | ||
414 | - assertThat(nextObjectives, hasSize(0)); | ||
415 | - } | ||
416 | } | 376 | } | ... | ... |
-
Please register or login to post a comment