Fixed a slew of shutdown exceptions that arose due to improper or out-of-order resource clean-up, e.g. listeners, timers, executors.

Change-Id: I37c351c4202b32e92c076d9d566b96d7ff8d313a
diff --git a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java
index 8db294b..3920e2d 100644
--- a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java
+++ b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java
@@ -73,6 +73,8 @@
 @Component(immediate = true)
 public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
 
+    private static final String PROVIDER_NAME = "org.onosproject.provider.lldp";
+
     private static final String PROP_USE_BDDP = "useBDDP";
     private static final String PROP_DISABLE_LD = "disableLinkDiscovery";
     private static final String PROP_LLDP_SUPPRESSION = "lldpSuppression";
@@ -132,13 +134,13 @@
      * Creates an OpenFlow link provider.
      */
     public LLDPLinkProvider() {
-        super(new ProviderId("lldp", "org.onosproject.provider.lldp"));
+        super(new ProviderId("lldp", PROVIDER_NAME));
     }
 
     @Activate
     public void activate(ComponentContext context) {
         cfgService.registerProperties(getClass());
-        appId = coreService.registerApplication("org.onosproject.provider.lldp");
+        appId = coreService.registerApplication(PROVIDER_NAME);
 
         // to load configuration at startup
         modified(context);
@@ -188,14 +190,14 @@
         if (disableLinkDiscovery) {
             return;
         }
-        executor.shutdownNow();
-        for (LinkDiscovery ld : discoverers.values()) {
-            ld.stop();
-        }
         providerRegistry.unregister(this);
         deviceService.removeListener(listener);
         packetService.removeProcessor(listener);
         masterService.removeListener(roleListener);
+
+        executor.shutdownNow();
+        discoverers.values().forEach(LinkDiscovery::stop);
+        discoverers.clear();
         providerService = null;
 
         log.info("Stopped");
diff --git a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java
index 005bd5c..6f3ffdc 100644
--- a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java
+++ b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java
@@ -104,8 +104,8 @@
         this.pktService = pktService;
 
         this.mastershipService = checkNotNull(masterService, "WTF!");
-        this.slowPorts = Collections.synchronizedSet(new HashSet<Long>());
-        this.fastPorts = Collections.synchronizedSet(new HashSet<Long>());
+        this.slowPorts = Collections.synchronizedSet(new HashSet<>());
+        this.fastPorts = Collections.synchronizedSet(new HashSet<>());
         this.portProbeCount = new HashMap<>();
         this.lldpPacket = new ONOSLLDP();
         this.lldpPacket.setChassisId(device.chassisId());
@@ -296,14 +296,14 @@
     }
 
     public synchronized void stop() {
-        timeout.cancel();
         isStopped = true;
+        timeout.cancel();
     }
 
     public synchronized void start() {
         if (isStopped) {
-            timeout = Timer.getTimer().newTimeout(this, 0, MILLISECONDS);
             isStopped = false;
+            timeout = Timer.getTimer().newTimeout(this, 0, MILLISECONDS);
         } else {
             log.warn("LinkDiscovery started multiple times?");
         }
@@ -361,8 +361,8 @@
         return slowPorts.contains(portNumber) || fastPorts.contains(portNumber);
     }
 
-    public boolean isStopped() {
-        return isStopped;
+    public synchronized boolean isStopped() {
+        return isStopped || timeout.isCancelled();
     }
 
 }