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