Reduces the dependency of the link providers on the ClusterMetadataService.

Provivers threads can be stuck on getting the cluster metadata.
Keep a local copy and update when receving the events

Change-Id: I5c83e5bbf166a003261dc15c0544b0bca23419d8
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 24d9a33..9ef85ce 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
@@ -20,6 +20,9 @@
 import com.google.common.collect.Maps;
 import org.onlab.packet.Ethernet;
 import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cluster.ClusterMetadata;
+import org.onosproject.cluster.ClusterMetadataEvent;
+import org.onosproject.cluster.ClusterMetadataEventListener;
 import org.onosproject.cluster.ClusterMetadataService;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.core.ApplicationId;
@@ -75,6 +78,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.atomic.AtomicReference;
 
 import static com.google.common.base.Strings.isNullOrEmpty;
 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
@@ -186,6 +190,9 @@
     // destination connection point is mastered by this controller instance.
     private final Map<LinkKey, Long> linkTimes = Maps.newConcurrentMap();
 
+    // Cache for clustermetadata
+    private AtomicReference<ClusterMetadata> clusterMetadata = new AtomicReference<>();
+
     private ApplicationId appId;
 
     static final SuppressionRules DEFAULT_RULES
@@ -228,6 +235,7 @@
     );
 
     private final InternalConfigListener cfgListener = new InternalConfigListener();
+    private final ClusterMetadataEventListener metadataListener = new InternalClusterMetadataListener();
 
     /**
      * Creates an OpenFlow link provider.
@@ -243,7 +251,7 @@
             return defMac;
         }
 
-        String srcMac = ProbedLinkProvider.fingerprintMac(clusterMetadataService.getClusterMetadata());
+        String srcMac = ProbedLinkProvider.fingerprintMac(clusterMetadata.get());
         if (srcMac.equals(defMac)) {
             log.warn("Couldn't generate fingerprint. Using default value {}", defMac);
             return defMac;
@@ -268,6 +276,10 @@
             cfg = this.setDefaultSuppressionConfig();
         }
         cfgListener.reconfigureSuppressionRules(cfg);
+        if (clusterMetadataService != null) {
+            clusterMetadataService.addListener(metadataListener);
+            clusterMetadata.set(clusterMetadataService.getClusterMetadata());
+        }
 
         modified(context);
         log.info("Started");
@@ -284,6 +296,9 @@
     @Deactivate
     public void deactivate() {
         shuttingDown = true;
+        if (clusterMetadataService != null) {
+            clusterMetadataService.removeListener(metadataListener);
+        }
         cfgRegistry.removeListener(cfgListener);
         factories.forEach(cfgRegistry::unregisterConfigFactory);
 
@@ -831,7 +846,8 @@
 
         @Override
         public String lldpSecret() {
-            return clusterMetadataService.getClusterMetadata().getClusterSecret();
+            return clusterMetadata.get() != null ?
+                    clusterMetadata.get().getClusterSecret() : null;
         }
 
         @Override
@@ -902,4 +918,11 @@
             });
         }
     }
+
+    private class InternalClusterMetadataListener implements ClusterMetadataEventListener {
+        @Override
+        public void event(ClusterMetadataEvent event) {
+            clusterMetadata.set(event.subject());
+        }
+    }
 }
diff --git a/providers/netcfglinks/src/main/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProvider.java b/providers/netcfglinks/src/main/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProvider.java
index e73163c..30608e4 100644
--- a/providers/netcfglinks/src/main/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProvider.java
+++ b/providers/netcfglinks/src/main/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProvider.java
@@ -17,6 +17,9 @@
 
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.ONOSLLDP;
+import org.onosproject.cluster.ClusterMetadata;
+import org.onosproject.cluster.ClusterMetadataEvent;
+import org.onosproject.cluster.ClusterMetadataEventListener;
 import org.onosproject.cluster.ClusterMetadataService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
@@ -64,6 +67,7 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicReference;
 
 import static org.onlab.packet.Ethernet.TYPE_BSN;
 import static org.onlab.packet.Ethernet.TYPE_LLDP;
@@ -106,7 +110,7 @@
     protected CoreService coreService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    protected ClusterMetadataService metadataService;
+    protected ClusterMetadataService clusterMetadataService;
 
     /** LLDP and BDDP probe rate specified in millis. */
     private int probeRate = PROBE_RATE_DEFAULT;
@@ -132,12 +136,15 @@
 
     protected Set<LinkKey> configuredLinks = new HashSet<>();
 
+    // Cache for clustermetadata
+    private AtomicReference<ClusterMetadata> clusterMetadata = new AtomicReference<>();
+
     public NetworkConfigLinksProvider() {
         super(new ProviderId("lldp", PROVIDER_NAME));
     }
 
     private String buildSrcMac() {
-        String srcMac = ProbedLinkProvider.fingerprintMac(metadataService.getClusterMetadata());
+        String srcMac = ProbedLinkProvider.fingerprintMac(clusterMetadata.get());
         String defMac = ProbedLinkProvider.defaultMac();
         if (srcMac.equals(defMac)) {
             log.warn("Couldn't generate fingerprint. Using default value {}", defMac);
@@ -152,6 +159,8 @@
                 .forEach(linkKey -> configuredLinks.add(linkKey));
     }
 
+    private final ClusterMetadataEventListener metadataListener = new InternalClusterMetadataListener();
+
     @Activate
     protected void activate() {
         log.info("Activated");
@@ -160,6 +169,8 @@
         providerService = providerRegistry.register(this);
         deviceService.addListener(deviceListener);
         netCfgService.addListener(cfgListener);
+        clusterMetadataService.addListener(metadataListener);
+        clusterMetadata.set(clusterMetadataService.getClusterMetadata());
         requestIntercepts();
         loadDevices();
         createLinks();
@@ -171,6 +182,7 @@
         providerRegistry.unregister(this);
         deviceService.removeListener(deviceListener);
         netCfgService.removeListener(cfgListener);
+        clusterMetadataService.removeListener(metadataListener);
         packetService.removeProcessor(packetProcessor);
         disable();
         log.info("Deactivated");
@@ -279,7 +291,8 @@
 
         @Override
         public String lldpSecret() {
-            return metadataService.getClusterMetadata().getClusterSecret();
+            return clusterMetadata.get() != null ?
+                    clusterMetadata.get().getClusterSecret() : null;
         }
 
         @Override
@@ -533,4 +546,11 @@
         }
     }
 
+    private class InternalClusterMetadataListener implements ClusterMetadataEventListener {
+        @Override
+        public void event(ClusterMetadataEvent event) {
+            clusterMetadata.set(event.subject());
+        }
+    }
+
 }
diff --git a/providers/netcfglinks/src/test/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProviderTest.java b/providers/netcfglinks/src/test/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProviderTest.java
index 13081f0..0678becd 100644
--- a/providers/netcfglinks/src/test/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProviderTest.java
+++ b/providers/netcfglinks/src/test/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProviderTest.java
@@ -233,7 +233,7 @@
         provider.deviceService = new TestDeviceManager();
         provider.masterService = new TestMastershipService();
         provider.packetService = new TestPacketService();
-        provider.metadataService = new ClusterMetadataServiceAdapter();
+        provider.clusterMetadataService = new ClusterMetadataServiceAdapter();
         provider.netCfgService = configRegistry;
 
         provider.activate();