Refactor static WAITING_JOB_LIST in ElanInstanceListener 79/66779/7
authorTom Pantelis <tompantelis@gmail.com>
Wed, 27 Dec 2017 17:59:58 +0000 (12:59 -0500)
committerTom Pantelis <tompantelis@gmail.com>
Mon, 19 Feb 2018 15:44:26 +0000 (10:44 -0500)
The WAITING_JOB_LIST functionality was moved to ElanInstanceCache.

Change-Id: I00910628748e59faf34bb19ccfb251f753b961ab
Signed-off-by: Tom Pantelis <tompantelis@gmail.com>
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/cache/ElanInstanceCache.java
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/listeners/ElanInstanceListener.java
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/utils/L2GatewayConnectionUtils.java

index d771271ad41e93993824c7940d5ca618921bd809..f55230ed1f731b35341546e6fb0d810c8f2decae 100644 (file)
@@ -8,6 +8,10 @@
 package org.opendaylight.netvirt.elan.cache;
 
 import com.google.common.base.Optional;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -31,6 +35,8 @@ import org.slf4j.LoggerFactory;
 public class ElanInstanceCache extends DataObjectCache<ElanInstance> {
     private static final Logger LOG = LoggerFactory.getLogger(ElanInstanceCache.class);
 
+    private final Map<InstanceIdentifier<ElanInstance>, Collection<Runnable>> waitingJobs = new HashMap<>();
+
     @Inject
     public ElanInstanceCache(DataBroker dataBroker, CacheProvider cacheProvider) {
         super(ElanInstance.class, dataBroker, LogicalDatastoreType.CONFIGURATION,
@@ -45,4 +51,31 @@ public class ElanInstanceCache extends DataObjectCache<ElanInstance> {
             return Optional.absent();
         }
     }
+
+    public Optional<ElanInstance> get(String elanInstanceName, Runnable runAfterElanIsAvailable) {
+        Optional<ElanInstance> possibleInstance = get(elanInstanceName);
+        if (!possibleInstance.isPresent()) {
+            synchronized (waitingJobs) {
+                possibleInstance = get(elanInstanceName);
+                if (!possibleInstance.isPresent()) {
+                    waitingJobs.computeIfAbsent(ElanHelper.getElanInstanceConfigurationDataPath(elanInstanceName),
+                        key -> new ArrayList<>()).add(runAfterElanIsAvailable);
+                }
+            }
+        }
+
+        return possibleInstance;
+    }
+
+    @Override
+    protected void added(InstanceIdentifier<ElanInstance> path, ElanInstance elanInstance) {
+        Collection<Runnable> jobsToRun;
+        synchronized (waitingJobs) {
+            jobsToRun = waitingJobs.remove(path);
+        }
+
+        if (jobsToRun != null) {
+            jobsToRun.forEach(Runnable::run);
+        }
+    }
 }
index d1fa8434ff0913cb313a5134db618578140a7097..af777508256d0b303c8c32ac5c75de7a5e78b32e 100644 (file)
@@ -7,10 +7,7 @@
  */
 package org.opendaylight.netvirt.elan.l2gw.listeners;
 
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -31,14 +28,12 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
-public class ElanInstanceListener extends AsyncClusteredDataTreeChangeListenerBase<ElanInstance,
-        ElanInstanceListener> {
+public class ElanInstanceListener extends AsyncClusteredDataTreeChangeListenerBase<ElanInstance, ElanInstanceListener> {
 
     private static final Logger LOG = LoggerFactory.getLogger(ElanInstanceListener.class);
 
     private final DataBroker broker;
     private final ElanClusterUtils elanClusterUtils;
-    private static final Map<String, List<Runnable>> WAITING_JOB_LIST = new ConcurrentHashMap<>();
 
     @Inject
     public ElanInstanceListener(final DataBroker db, final ElanClusterUtils elanClusterUtils) {
@@ -86,15 +81,6 @@ public class ElanInstanceListener extends AsyncClusteredDataTreeChangeListenerBa
 
     @Override
     protected void add(InstanceIdentifier<ElanInstance> identifier, ElanInstance add) {
-        List<Runnable> runnables = WAITING_JOB_LIST.get(add.getElanInstanceName());
-        if (runnables != null) {
-            runnables.forEach(Runnable::run);
-        }
-    }
-
-    public static void runJobAfterElanIsAvailable(String elanName, Runnable runnable) {
-        WAITING_JOB_LIST.computeIfAbsent(elanName, (name) -> new ArrayList<>());
-        WAITING_JOB_LIST.get(elanName).add(runnable);
     }
 
     @Override
index 48f16049162389e9943d0df5bc12d1edb30ac55a..68684ac622f7b49d76d9137f713a7c0854979a3a 100644 (file)
@@ -35,7 +35,6 @@ import org.opendaylight.netvirt.elan.internal.ElanInstanceManager;
 import org.opendaylight.netvirt.elan.l2gw.ha.listeners.HAOpClusteredListener;
 import org.opendaylight.netvirt.elan.l2gw.jobs.AssociateHwvtepToElanJob;
 import org.opendaylight.netvirt.elan.l2gw.jobs.DisAssociateHwvtepFromElanJob;
-import org.opendaylight.netvirt.elan.l2gw.listeners.ElanInstanceListener;
 import org.opendaylight.netvirt.elan.l2gw.listeners.HwvtepLogicalSwitchListener;
 import org.opendaylight.netvirt.elan.l2gw.listeners.LocalUcastMacListener;
 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
@@ -190,16 +189,16 @@ public class L2GatewayConnectionUtils implements AutoCloseable {
         LOG.info("Adding L2gateway Connection with ID: {}", input.getKey().getUuid());
 
         Uuid networkUuid = input.getNetworkId();
-        ElanInstance elanInstance = elanInstanceManager.getElanInstanceByName(networkUuid.getValue());
-        //Taking cluster reboot scenario , if Elan instance is not available when l2GatewayConnection add events
-        //comes we need to wait for elaninstance to resolve. Hence updating the map with the runnable .
-        //When elanInstance add comes , it look in to the map and run the associated runnable associated with it.
+
+        // Taking cluster reboot scenario , if Elan instance is not available when l2GatewayConnection add events
+        // comes we need to wait for elaninstance to resolve. Hence updating the map with the runnable .
+        // When elanInstance add comes , it look in to the map and run the associated runnable associated with it.
+        ElanInstance elanInstance = elanInstanceCache.get(networkUuid.getValue(),
+            () -> addL2GatewayConnection(input, l2GwDeviceName)).orNull();
         if (elanInstance == null) {
-            LOG.info("Waiting for elan {}", networkUuid.getValue());
-            ElanInstanceListener.runJobAfterElanIsAvailable(networkUuid.getValue(),
-                () -> addL2GatewayConnection(input, l2GwDeviceName));
             return;
         }
+
         if (!isVxlanNetworkOrVxlanSegment(elanInstance)) {
             LOG.error("Neutron network with id {} is not VxlanNetwork", networkUuid.getValue());
         } else {