TSC-181 : ITM Yang Models Cleanup
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / utils / ElanUtils.java
index 99230771cab91053932406194984844c1c595703..a25c8a25eed3c7b10a2475eca48ccbe96fbee4e6 100755 (executable)
@@ -32,7 +32,6 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import javax.inject.Inject;
 import javax.inject.Singleton;
-
 import org.apache.commons.lang3.StringUtils;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
@@ -74,8 +73,9 @@ import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
 import org.opendaylight.genius.mdsalutil.packet.ARP;
 import org.opendaylight.genius.mdsalutil.packet.Ethernet;
 import org.opendaylight.genius.mdsalutil.packet.IPv4;
-import org.opendaylight.infrautils.utils.concurrent.JdkFutures;
-import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
+import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
+import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
+import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
 import org.opendaylight.netvirt.elan.arp.responder.ArpResponderUtil;
 import org.opendaylight.netvirt.elan.cache.ElanInterfaceCache;
 import org.opendaylight.netvirt.elanmanager.api.ElanHelper;
@@ -190,8 +190,38 @@ import org.slf4j.LoggerFactory;
 
 @Singleton
 public class ElanUtils {
+    private static final class ElanLockName {
+        private final String macAddress;
+        private final BigInteger dpnId;
+        private final long elanTag;
+
+        ElanLockName(long elanTag, String macAddress, BigInteger dpnId) {
+            this.elanTag = elanTag;
+            this.macAddress = macAddress;
+            this.dpnId = dpnId;
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 * Long.hashCode(elanTag) + Objects.hash(macAddress, dpnId);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!(obj instanceof ElanLockName)) {
+                return false;
+            }
+            final ElanLockName other = (ElanLockName) obj;
+            return elanTag == other.elanTag && Objects.equals(macAddress, other.macAddress)
+                    && Objects.equals(dpnId, other.dpnId);
+        }
+    }
 
     private static final Logger LOG = LoggerFactory.getLogger(ElanUtils.class);
+    private static final NamedLocks<ElanLockName> ELAN_LOCKS = new NamedLocks<>();
 
     private final DataBroker broker;
     private final ManagedNewTransactionRunner txRunner;
@@ -270,7 +300,7 @@ public class ElanUtils {
 
     public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
         ReleaseIdInput releaseIdInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
-        JdkFutures.addErrorLogging(idManager.releaseId(releaseIdInput), LOG, "Release Id");
+        LoggingFutures.addErrorLogging(idManager.releaseId(releaseIdInput), LOG, "Release Id");
     }
 
     /**
@@ -567,7 +597,7 @@ public class ElanUtils {
     public void setupMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
                               long macTimeout, String macAddress, boolean configureRemoteFlows,
                               TypedWriteTransaction<Configuration> writeFlowGroupTx) {
-        synchronized (getElanMacDPNKey(elanInfo.getElanTag(), macAddress, interfaceInfo.getDpId())) {
+        try (Acquired lock = lockElanMacDPN(elanInfo.getElanTag(), macAddress, interfaceInfo.getDpId())) {
             setupKnownSmacFlow(elanInfo, interfaceInfo, macTimeout, macAddress, mdsalManager,
                 writeFlowGroupTx);
             setupOrigDmacFlows(elanInfo, interfaceInfo, macAddress, configureRemoteFlows, mdsalManager,
@@ -681,7 +711,7 @@ public class ElanUtils {
      * @return the Internal tunnel
      */
     public static String getIntTunnelTableFlowRef(short tableId, int elanTag) {
-        return new StringBuffer().append(tableId).append(elanTag).toString();
+        return new StringBuilder().append(tableId).append(elanTag).toString();
     }
 
     /**
@@ -1001,7 +1031,7 @@ public class ElanUtils {
             return;
         }
         String macAddress = macEntry.getMacAddress().getValue();
-        synchronized (getElanMacDPNKey(elanInfo.getElanTag(), macAddress, interfaceInfo.getDpId())) {
+        try (Acquired lock = lockElanMacDPN(elanInfo.getElanTag(), macAddress, interfaceInfo.getDpId())) {
             deleteMacFlows(elanInfo, interfaceInfo, macAddress, /* alsoDeleteSMAC */ true, flowTx);
         }
     }
@@ -1403,7 +1433,7 @@ public class ElanUtils {
     public void addDmacRedirectToDispatcherFlows(Long elanTag, String displayName,
             String macAddress, List<BigInteger> dpnIds) {
         for (BigInteger dpId : dpnIds) {
-            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+            LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
                 tx -> mdsalManager.addFlow(tx, buildDmacRedirectToDispatcherFlow(dpId, macAddress, displayName,
                         elanTag))), LOG,
                 "Error adding DMAC redirect to dispatcher flows");
@@ -1411,7 +1441,7 @@ public class ElanUtils {
     }
 
     public void removeDmacRedirectToDispatcherFlows(Long elanTag, String macAddress, List<BigInteger> dpnIds) {
-        ListenableFutures.addErrorLogging(
+        LoggingFutures.addErrorLogging(
             txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION, tx -> {
                 for (BigInteger dpId : dpnIds) {
                     String flowId = getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, macAddress, elanTag);
@@ -1454,14 +1484,8 @@ public class ElanUtils {
         return null;
     }
 
-    public static String getElanMacDPNKey(long elanTag, String macAddress, BigInteger dpnId) {
-        String elanMacDmacDpnKey = "MAC-" + macAddress + " ELAN_TAG-" + elanTag + "DPN_ID-" + dpnId;
-        return elanMacDmacDpnKey.intern();
-    }
-
-    public static String getElanMacKey(long elanTag, String macAddress) {
-        String elanMacKey = "MAC-" + macAddress + " ELAN_TAG-" + elanTag;
-        return elanMacKey.intern();
+    public static Acquired lockElanMacDPN(long elanTag, String macAddress, BigInteger dpnId) {
+        return ELAN_LOCKS.acquire(new ElanLockName(elanTag, macAddress, dpnId));
     }
 
     public static List<ListenableFuture<Void>>
@@ -1588,7 +1612,7 @@ public class ElanUtils {
             int lportTag) {
         LOG.info("Removing the ARP responder flow on DPN {} of Interface {} with IP {}", dpnId, ingressInterfaceName,
                 ipAddress);
-        ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION,
+        LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION,
             tx -> mdsalManager.removeFlow(tx, dpnId, ArpResponderUtil.getFlowId(lportTag, ipAddress),
                 NwConstants.ARP_RESPONDER_TABLE)), LOG, "Error removing ARP responder flow");
     }