NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / internal / ElanInterfaceManager.java
index 978a75b79d4fbe382dcbd3e138dd420b0c75403d..0ed67f922045a8058631386af807b8798a22853f 100644 (file)
@@ -8,15 +8,15 @@
 package org.opendaylight.netvirt.elan.internal;
 
 import static java.util.Collections.emptyList;
-import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
 import static org.opendaylight.infrautils.utils.concurrent.LoggingFutures.addErrorLogging;
+import static org.opendaylight.mdsal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
 import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlanNetworkOrVxlanSegment;
 
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.FluentFuture;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
 import java.util.ArrayList;
@@ -25,25 +25,21 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.locks.ReentrantLock;
-import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.apache.commons.lang3.StringUtils;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
 import org.opendaylight.genius.infra.Datastore.Configuration;
 import org.opendaylight.genius.infra.Datastore.Operational;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
-import org.opendaylight.genius.infra.TransactionAdapter;
 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
 import org.opendaylight.genius.infra.TypedWriteTransaction;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
@@ -71,8 +67,11 @@ import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
 import org.opendaylight.genius.utils.JvmGlobalLocks;
 import org.opendaylight.genius.utils.ServiceIndex;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.infrautils.utils.concurrent.Executors;
 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
 import org.opendaylight.netvirt.elan.cache.ElanInterfaceCache;
 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
@@ -90,6 +89,7 @@ import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
 import org.opendaylight.serviceutils.srm.RecoverableListener;
 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
+import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
@@ -151,7 +151,7 @@ import org.slf4j.LoggerFactory;
  * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface
  */
 @Singleton
-public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanInterface, ElanInterfaceManager>
+public class ElanInterfaceManager extends AbstractAsyncDataTreeChangeListener<ElanInterface>
         implements RecoverableListener {
     private static final Logger LOG = LoggerFactory.getLogger(ElanInterfaceManager.class);
     private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("NetvirtEventLogger");
@@ -192,7 +192,9 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                                 final ElanServiceRecoveryHandler elanServiceRecoveryHandler,
                                 ElanGroupCache elanGroupCache,
                                 final ServiceRecoveryRegistry serviceRecoveryRegistry) {
-        super(ElanInterface.class, ElanInterfaceManager.class);
+        super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(ElanInterfaces.class)
+                .child(ElanInterface.class),
+                Executors.newListeningSingleThreadExecutor("ElanInterfaceManager", LOG));
         this.broker = dataBroker;
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.idManager = managerService;
@@ -212,24 +214,31 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         serviceRecoveryRegistry.addRecoverableListener(elanServiceRecoveryHandler.buildServiceRegistryKey(), this);
     }
 
-    @Override
-    @PostConstruct
     public void init() {
-        registerListener();
+        LOG.info("{} registered", getClass().getSimpleName());
     }
 
     @Override
     public void registerListener() {
-        registerListener(LogicalDatastoreType.CONFIGURATION, broker);
+        super.register();
+        LOG.info("Registering ElanInterfaceManager");
+    }
+
+    @Override
+    public void deregisterListener() {
+        super.close();
+        LOG.info("Deregistering ElanInterfaceManager");
     }
 
     @Override
-    protected InstanceIdentifier<ElanInterface> getWildCardPath() {
-        return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
+    @PreDestroy
+    public void close() {
+        super.close();
+        Executors.shutdownAndAwaitTermination(getExecutorService());
     }
 
     @Override
-    protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
+    public void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
         String interfaceName = del.getName();
         String elanInstanceName = del.getElanInstanceName();
         EVENT_LOGGER.debug("ELAN-Interface, REMOVE {} Instance {}", interfaceName, elanInstanceName);
@@ -240,7 +249,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 unProcessedElanInterfaces.remove(elanInstanceName);
             }
         }
-        ElanInstance elanInfo = elanInstanceCache.get(elanInstanceName).orNull();
+        ElanInstance elanInfo = elanInstanceCache.get(elanInstanceName).orElse(null);
         /*
          * Handling in case the elan instance is deleted.If the Elan instance is
          * deleted, there is no need to explicitly delete the elan interfaces
@@ -402,12 +411,13 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     }
 
     private void deleteElanInterfaceFromConfigDS(String interfaceName, TypedReadWriteTransaction<Configuration> tx)
-            throws ReadFailedException {
+            throws ExecutionException, InterruptedException {
         // removing the ElanInterface from the config data_store if interface is
         // not present in Interface config DS
-        if (interfaceManager.getInterfaceInfoFromConfigDataStore(TransactionAdapter.toReadWriteTransaction(tx),
-            interfaceName) == null
-                && elanInterfaceCache.get(interfaceName).isPresent()) {
+        InstanceIdentifier<ElanInterface> elanInterfaceId = ElanUtils
+                .getElanInterfaceConfigurationDataPathId(interfaceName);
+        FluentFuture<Optional<ElanInterface>> interfaceOptional = tx.read(elanInterfaceId);
+        if (!interfaceOptional.get().isPresent() && elanInterfaceCache.get(interfaceName).isPresent()) {
             tx.delete(ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
         }
     }
@@ -562,7 +572,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     * */
     @SuppressWarnings("checkstyle:ForbidCertainMethod")
     @Override
-    protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
+    public void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
         // updating the static-Mac Entries for the existing elanInterface
         String elanName = update.getElanInstanceName();
         String interfaceName = update.getName();
@@ -602,7 +612,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     }
 
     @Override
-    protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
+    public void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
         LOG.info("Init for ELAN interface Add {}", elanInterfaceAdded);
         addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx -> {
             String elanInstanceName = elanInterfaceAdded.getElanInstanceName();
@@ -613,7 +623,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 LOG.info("Interface {} is removed from Interface Oper DS due to port down ", interfaceName);
                 return;
             }
-            ElanInstance elanInstance = elanInstanceCache.get(elanInstanceName).orNull();
+            ElanInstance elanInstance = elanInstanceCache.get(elanInstanceName).orElse(null);
 
             if (elanInstance == null) {
                 // Add the ElanInstance in the Configuration data-store
@@ -637,6 +647,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 if (!elanInterfaces.contains(elanInterfaceAdded)) {
                     elanInterfaces.add(elanInterfaceAdded);
                 }
+                LOG.error("ELAN tag for instance {} is not created. Adding it to unprocessed list."
+                        + " Recreate the network if this message is seen multiple times", elanInstanceName);
                 unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
                 return;
             }
@@ -922,7 +934,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName)
                 .withKey(new MacEntryKey(physAddress)).build();
         elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(
-                elanInstanceCache.get(elanInstanceName).orNull(), interfaceInfo, macEntry);
+                elanInstanceCache.get(elanInstanceName).orElse(null), interfaceInfo, macEntry);
     }
 
     private boolean checkIfFirstInterface(String elanInterface, String elanInstanceName,
@@ -1587,7 +1599,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
             int cnt = 0;
             String elanName = elanDpns.getElanInstanceName();
-            ElanInstance elanInfo = elanInstanceCache.get(elanName).orNull();
+            ElanInstance elanInfo = elanInstanceCache.get(elanName).orElse(null);
             if (elanInfo == null) {
                 LOG.warn("ELAN Info is null for elanName {} that does exist in elanDpnInterfaceList, "
                         + "skipping this ELAN for tunnel handling", elanName);
@@ -1678,7 +1690,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.nonnullElanDpnInterfacesList();
         for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
             String elanName = elanDpns.getElanInstanceName();
-            ElanInstance elanInfo = elanInstanceCache.get(elanName).orNull();
+            ElanInstance elanInfo = elanInstanceCache.get(elanName).orElse(null);
 
             DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
             if (elanInfo == null || dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
@@ -1789,11 +1801,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         return mkMatches;
     }
 
-    @Override
-    protected ElanInterfaceManager getDataTreeChangeListener() {
-        return this;
-    }
-
     public void handleExternalInterfaceEvent(ElanInstance elanInstance, DpnInterfaces dpnInterfaces,
                                              Uint64 dpId) {
         LOG.debug("setting up remote BC group for elan {}", elanInstance.getPhysicalNetworkName());