Handling RACE conditions in bind/unbind service
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / renderer / ovs / statehelpers / OvsInterfaceTopologyStateUpdateHelper.java
index f1fef81d30253fb042b2e8c29d1954e9b014aa79..b1c0a7d33af363736e1973a4aff7e7a09d169ca0 100644 (file)
@@ -8,24 +8,26 @@
 package org.opendaylight.genius.interfacemanager.renderer.ovs.statehelpers;
 
 import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
 import org.opendaylight.genius.interfacemanager.IfmUtil;
 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
+import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.IfmClusterUtils;
 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge._interface.info.BridgeEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge._interface.info.BridgeEntry;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-
 public class OvsInterfaceTopologyStateUpdateHelper {
     private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceTopologyStateUpdateHelper.class);
 
@@ -61,38 +63,44 @@ public class OvsInterfaceTopologyStateUpdateHelper {
         return futures;
     }
 
-    public static List<ListenableFuture<Void>> updateTunnelState(DataBroker dataBroker,
+    public static List<ListenableFuture<Void>> updateTunnelState(final DataBroker dataBroker,
                                                                  OvsdbTerminationPointAugmentation terminationPointNew) {
-        List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
-
-        if (InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(terminationPointNew.getName(), dataBroker) == null) {
-            return futures;
-        }
-        // update opstate of interface if TEP has gone down/up as a result of BFD monitoring
-        LOG.debug("updating tunnel state for interface {}", terminationPointNew.getName());
-        WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
-        InterfaceManagerCommonUtils.updateOpState(transaction, terminationPointNew.getName(), getTunnelOpState(terminationPointNew.getInterfaceBfdStatus()));
-        futures.add(transaction.submit());
-        return futures;
+        final Interface.OperStatus interfaceBfdStatus = getTunnelOpState(terminationPointNew.getInterfaceBfdStatus());
+        final String interfaceName = terminationPointNew.getName();
+        InterfaceManagerCommonUtils.addBfdStateToCache(interfaceName, interfaceBfdStatus);
+        IfmClusterUtils.runOnlyInLeaderNode(() -> {
+            DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+            jobCoordinator.enqueueJob(interfaceName, () -> {
+                // update opstate of interface if TEP has gone down/up as a result of BFD monitoring
+                final List<ListenableFuture<Void>> futures = new ArrayList<>();
+                final Interface interfaceState = InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(
+                    terminationPointNew.getName(), dataBroker);
+                if (interfaceState != null && interfaceState.getOperStatus() != Interface.OperStatus.Unknown &&
+                    interfaceState.getOperStatus() != interfaceBfdStatus) {
+                    LOG.debug("updating tunnel state for interface {}", interfaceName);
+                    WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+                    InterfaceManagerCommonUtils.updateOpState(transaction, interfaceName,
+                        interfaceBfdStatus);
+                    futures.add(transaction.submit());
+                }
+                return futures;
+            });
+        }, IfmClusterUtils.INTERFACE_CONFIG_ENTITY);
+        return null;
     }
 
-    private static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus
-    getTunnelOpState(List<InterfaceBfdStatus> tunnelBfdStatus) {
-        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus
-                livenessState = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+    private static Interface.OperStatus getTunnelOpState(List<InterfaceBfdStatus> tunnelBfdStatus) {
+        Interface.OperStatus livenessState = Interface.OperStatus.Down;
         if (tunnelBfdStatus != null && !tunnelBfdStatus.isEmpty()) {
             for (InterfaceBfdStatus bfdState : tunnelBfdStatus) {
                 if (bfdState.getBfdStatusKey().equalsIgnoreCase(SouthboundUtils.BFD_OP_STATE)) {
                     String bfdOpState = bfdState.getBfdStatusValue();
-                    if (bfdOpState.equalsIgnoreCase(SouthboundUtils.BFD_STATE_UP)) {
-                        livenessState = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up;
-                    } else {
-                        livenessState = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
-                    }
+                    livenessState = SouthboundUtils.BFD_STATE_UP.equalsIgnoreCase(bfdOpState) ?
+                         Interface.OperStatus.Up : Interface.OperStatus.Down;
                     break;
                 }
             }
         }
         return livenessState;
     }
-}
\ No newline at end of file
+}