Ray Milkey
Committed by Gerrit Code Review

Fix ONOS-4683 - Don't process device events on the listener thread

Change-Id: Icc465311c2c047dba11bacc69c745bbda55ea714
...@@ -15,9 +15,16 @@ ...@@ -15,9 +15,16 @@
15 */ 15 */
16 package org.onosproject.provider.lldp.impl; 16 package org.onosproject.provider.lldp.impl;
17 17
18 -import com.google.common.collect.ImmutableMap; 18 +import java.util.Dictionary;
19 -import com.google.common.collect.ImmutableSet; 19 +import java.util.EnumSet;
20 -import com.google.common.collect.Maps; 20 +import java.util.Map;
21 +import java.util.Optional;
22 +import java.util.Properties;
23 +import java.util.Set;
24 +import java.util.concurrent.ConcurrentHashMap;
25 +import java.util.concurrent.ExecutorService;
26 +import java.util.concurrent.ScheduledExecutorService;
27 +
21 import org.apache.felix.scr.annotations.Activate; 28 import org.apache.felix.scr.annotations.Activate;
22 import org.apache.felix.scr.annotations.Component; 29 import org.apache.felix.scr.annotations.Component;
23 import org.apache.felix.scr.annotations.Deactivate; 30 import org.apache.felix.scr.annotations.Deactivate;
...@@ -26,7 +33,6 @@ import org.apache.felix.scr.annotations.Property; ...@@ -26,7 +33,6 @@ import org.apache.felix.scr.annotations.Property;
26 import org.apache.felix.scr.annotations.Reference; 33 import org.apache.felix.scr.annotations.Reference;
27 import org.apache.felix.scr.annotations.ReferenceCardinality; 34 import org.apache.felix.scr.annotations.ReferenceCardinality;
28 import org.onlab.packet.Ethernet; 35 import org.onlab.packet.Ethernet;
29 -import org.onlab.util.SharedExecutors;
30 import org.onosproject.cfg.ComponentConfigService; 36 import org.onosproject.cfg.ComponentConfigService;
31 import org.onosproject.cluster.ClusterMetadataService; 37 import org.onosproject.cluster.ClusterMetadataService;
32 import org.onosproject.cluster.ClusterService; 38 import org.onosproject.cluster.ClusterService;
...@@ -51,29 +57,24 @@ import org.onosproject.net.device.DeviceService; ...@@ -51,29 +57,24 @@ import org.onosproject.net.device.DeviceService;
51 import org.onosproject.net.flow.DefaultTrafficSelector; 57 import org.onosproject.net.flow.DefaultTrafficSelector;
52 import org.onosproject.net.flow.TrafficSelector; 58 import org.onosproject.net.flow.TrafficSelector;
53 import org.onosproject.net.link.DefaultLinkDescription; 59 import org.onosproject.net.link.DefaultLinkDescription;
54 -import org.onosproject.net.link.ProbedLinkProvider;
55 import org.onosproject.net.link.LinkProviderRegistry; 60 import org.onosproject.net.link.LinkProviderRegistry;
56 import org.onosproject.net.link.LinkProviderService; 61 import org.onosproject.net.link.LinkProviderService;
57 import org.onosproject.net.link.LinkService; 62 import org.onosproject.net.link.LinkService;
63 +import org.onosproject.net.link.ProbedLinkProvider;
58 import org.onosproject.net.packet.PacketContext; 64 import org.onosproject.net.packet.PacketContext;
59 import org.onosproject.net.packet.PacketPriority; 65 import org.onosproject.net.packet.PacketPriority;
60 import org.onosproject.net.packet.PacketProcessor; 66 import org.onosproject.net.packet.PacketProcessor;
61 import org.onosproject.net.packet.PacketService; 67 import org.onosproject.net.packet.PacketService;
62 import org.onosproject.net.provider.AbstractProvider; 68 import org.onosproject.net.provider.AbstractProvider;
63 import org.onosproject.net.provider.ProviderId; 69 import org.onosproject.net.provider.ProviderId;
64 -import org.onosproject.provider.lldpcommon.LinkDiscoveryContext;
65 import org.onosproject.provider.lldpcommon.LinkDiscovery; 70 import org.onosproject.provider.lldpcommon.LinkDiscovery;
71 +import org.onosproject.provider.lldpcommon.LinkDiscoveryContext;
66 import org.osgi.service.component.ComponentContext; 72 import org.osgi.service.component.ComponentContext;
67 import org.slf4j.Logger; 73 import org.slf4j.Logger;
68 74
69 -import java.util.Dictionary; 75 +import com.google.common.collect.ImmutableMap;
70 -import java.util.EnumSet; 76 +import com.google.common.collect.ImmutableSet;
71 -import java.util.Map; 77 +import com.google.common.collect.Maps;
72 -import java.util.Optional;
73 -import java.util.Properties;
74 -import java.util.Set;
75 -import java.util.concurrent.ConcurrentHashMap;
76 -import java.util.concurrent.ScheduledExecutorService;
77 78
78 import static com.google.common.base.Strings.isNullOrEmpty; 79 import static com.google.common.base.Strings.isNullOrEmpty;
79 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; 80 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
...@@ -141,6 +142,7 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv ...@@ -141,6 +142,7 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv
141 private LinkProviderService providerService; 142 private LinkProviderService providerService;
142 143
143 private ScheduledExecutorService executor; 144 private ScheduledExecutorService executor;
145 + protected ExecutorService eventExecutor;
144 146
145 private boolean shuttingDown = false; 147 private boolean shuttingDown = false;
146 148
...@@ -240,6 +242,7 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv ...@@ -240,6 +242,7 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv
240 242
241 @Activate 243 @Activate
242 public void activate(ComponentContext context) { 244 public void activate(ComponentContext context) {
245 + eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/linkevents", "events-%d", log));
243 shuttingDown = false; 246 shuttingDown = false;
244 cfgService.registerProperties(getClass()); 247 cfgService.registerProperties(getClass());
245 appId = coreService.registerApplication(PROVIDER_NAME); 248 appId = coreService.registerApplication(PROVIDER_NAME);
...@@ -274,6 +277,8 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv ...@@ -274,6 +277,8 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv
274 277
275 cfgService.unregisterProperties(getClass(), false); 278 cfgService.unregisterProperties(getClass(), false);
276 disable(); 279 disable();
280 + eventExecutor.shutdownNow();
281 + eventExecutor = null;
277 log.info("Stopped"); 282 log.info("Stopped");
278 } 283 }
279 284
...@@ -542,27 +547,30 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv ...@@ -542,27 +547,30 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv
542 return; 547 return;
543 } 548 }
544 549
545 - DeviceId deviceId = event.subject(); 550 + eventExecutor.execute(() -> {
546 - Device device = deviceService.getDevice(deviceId); 551 + DeviceId deviceId = event.subject();
547 - if (device == null) { 552 + Device device = deviceService.getDevice(deviceId);
548 - log.debug("Device {} doesn't exist, or isn't there yet", deviceId); 553 + if (device == null) {
549 - return; 554 + log.debug("Device {} doesn't exist, or isn't there yet", deviceId);
550 - } 555 + return;
551 - if (clusterService.getLocalNode().id().equals(event.roleInfo().master())) { 556 + }
552 - updateDevice(device).ifPresent(ld -> updatePorts(ld, device.id())); 557 + if (clusterService.getLocalNode().id().equals(event.roleInfo().master())) {
553 - } 558 + updateDevice(device).ifPresent(ld -> updatePorts(ld, device.id()));
559 + }
560 + });
554 } 561 }
555 } 562 }
556 563
557 - /** 564 + private class DeviceEventProcessor implements Runnable {
558 - * Processes device events. 565 +
559 - */ 566 + DeviceEvent event;
560 - private class InternalDeviceListener implements DeviceListener { 567 +
568 + DeviceEventProcessor(DeviceEvent event) {
569 + this.event = event;
570 + }
571 +
561 @Override 572 @Override
562 - public void event(DeviceEvent event) { 573 + public void run() {
563 - if (event.type() == Type.PORT_STATS_UPDATED) {
564 - return;
565 - }
566 Device device = event.subject(); 574 Device device = event.subject();
567 Port port = event.port(); 575 Port port = event.port();
568 if (device == null) { 576 if (device == null) {
...@@ -618,6 +626,22 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv ...@@ -618,6 +626,22 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv
618 } 626 }
619 627
620 /** 628 /**
629 + * Processes device events.
630 + */
631 + private class InternalDeviceListener implements DeviceListener {
632 + @Override
633 + public void event(DeviceEvent event) {
634 + if (event.type() == Type.PORT_STATS_UPDATED) {
635 + return;
636 + }
637 +
638 + Runnable deviceEventProcessor = new DeviceEventProcessor(event);
639 +
640 + eventExecutor.execute(deviceEventProcessor);
641 + }
642 + }
643 +
644 + /**
621 * Processes incoming packets. 645 * Processes incoming packets.
622 */ 646 */
623 private class InternalPacketProcessor implements PacketProcessor { 647 private class InternalPacketProcessor implements PacketProcessor {
...@@ -774,7 +798,7 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv ...@@ -774,7 +798,7 @@ public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProv
774 798
775 @Override 799 @Override
776 public void event(NetworkConfigEvent event) { 800 public void event(NetworkConfigEvent event) {
777 - SharedExecutors.getPoolThreadExecutor().execute(() -> { 801 + eventExecutor.execute(() -> {
778 if (event.configClass() == LinkDiscoveryFromDevice.class && 802 if (event.configClass() == LinkDiscoveryFromDevice.class &&
779 CONFIG_CHANGED.contains(event.type())) { 803 CONFIG_CHANGED.contains(event.type())) {
780 804
......
...@@ -15,11 +15,15 @@ ...@@ -15,11 +15,15 @@
15 */ 15 */
16 package org.onosproject.provider.lldp.impl; 16 package org.onosproject.provider.lldp.impl;
17 17
18 -import com.google.common.collect.ArrayListMultimap; 18 +import java.nio.ByteBuffer;
19 -import com.google.common.collect.ImmutableList; 19 +import java.util.Collections;
20 -import com.google.common.collect.ImmutableMap; 20 +import java.util.HashMap;
21 -import com.google.common.collect.ImmutableSet; 21 +import java.util.HashSet;
22 -import com.google.common.collect.Lists; 22 +import java.util.List;
23 +import java.util.Map;
24 +import java.util.Set;
25 +import java.util.concurrent.CompletableFuture;
26 +
23 import org.junit.After; 27 import org.junit.After;
24 import org.junit.Before; 28 import org.junit.Before;
25 import org.junit.Test; 29 import org.junit.Test;
...@@ -66,14 +70,12 @@ import org.onosproject.net.packet.PacketServiceAdapter; ...@@ -66,14 +70,12 @@ import org.onosproject.net.packet.PacketServiceAdapter;
66 import org.onosproject.net.provider.ProviderId; 70 import org.onosproject.net.provider.ProviderId;
67 import org.onosproject.provider.lldpcommon.LinkDiscovery; 71 import org.onosproject.provider.lldpcommon.LinkDiscovery;
68 72
69 -import java.nio.ByteBuffer; 73 +import com.google.common.collect.ArrayListMultimap;
70 -import java.util.Collections; 74 +import com.google.common.collect.ImmutableList;
71 -import java.util.HashMap; 75 +import com.google.common.collect.ImmutableMap;
72 -import java.util.HashSet; 76 +import com.google.common.collect.ImmutableSet;
73 -import java.util.List; 77 +import com.google.common.collect.Lists;
74 -import java.util.Map; 78 +import com.google.common.util.concurrent.MoreExecutors;
75 -import java.util.Set;
76 -import java.util.concurrent.CompletableFuture;
77 79
78 import static org.easymock.EasyMock.createMock; 80 import static org.easymock.EasyMock.createMock;
79 import static org.easymock.EasyMock.expect; 81 import static org.easymock.EasyMock.expect;
...@@ -146,6 +148,8 @@ public class LldpLinkProviderTest { ...@@ -146,6 +148,8 @@ public class LldpLinkProviderTest {
146 148
147 provider.activate(null); 149 provider.activate(null);
148 150
151 + provider.eventExecutor = MoreExecutors.newDirectExecutorService();
152 +
149 providerService = linkRegistry.registeredProvider(); 153 providerService = linkRegistry.registeredProvider();
150 } 154 }
151 155
......
...@@ -255,6 +255,9 @@ public class LinkDiscovery implements TimerTask { ...@@ -255,6 +255,9 @@ public class LinkDiscovery implements TimerTask {
255 } 255 }
256 256
257 private void sendProbes(Long portNumber) { 257 private void sendProbes(Long portNumber) {
258 + if (context.packetService() == null) {
259 + return;
260 + }
258 log.trace("Sending probes out to {}@{}", portNumber, device.id()); 261 log.trace("Sending probes out to {}@{}", portNumber, device.id());
259 OutboundPacket pkt = createOutBoundLldp(portNumber); 262 OutboundPacket pkt = createOutBoundLldp(portNumber);
260 context.packetService().emit(pkt); 263 context.packetService().emit(pkt);
......