Fix deprecation warnings around addAugmentation()
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / HwvtepDeviceInfo.java
index d217ebc034a9a7edfca6556358c360f7a15bda80..6c846a9a9c766bfeb9e26a59fab6e471d3e5b205 100644 (file)
@@ -5,9 +5,16 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-
 package org.opendaylight.ovsdb.hwvtepsouthbound;
 
+import com.google.common.collect.Sets;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependencyQueue;
 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependentJob;
 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.TransactCommand;
@@ -15,18 +22,17 @@ import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalSwitch;
+import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionHistory;
+import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
 /*
  * HwvtepDeviceInfo is used to store some of the table entries received
  * in updates from a Hwvtep device. There will be one instance of this per
@@ -49,6 +55,24 @@ public class HwvtepDeviceInfo {
 
     private static final Logger LOG = LoggerFactory.getLogger(HwvtepDeviceInfo.class);
 
+    private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, Boolean>> availableInOperDs =
+            new ConcurrentHashMap<>();
+
+    public void markAvailableInOperDs(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+        availableInOperDs.putIfAbsent(cls, new ConcurrentHashMap<>());
+        availableInOperDs.get(cls).put(key, Boolean.TRUE);
+    }
+
+    public Boolean isAvailableInOperDs(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+        availableInOperDs.putIfAbsent(cls, new ConcurrentHashMap<>());
+        return availableInOperDs.get(cls).getOrDefault(key, Boolean.FALSE);
+    }
+
+    public Boolean clearOperDsAvailability(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+        availableInOperDs.putIfAbsent(cls, new ConcurrentHashMap<>());
+        return availableInOperDs.get(cls).remove(key);
+    }
+
     public enum DeviceDataStatus {
         IN_TRANSIT,
         UNAVAILABLE,
@@ -60,12 +84,16 @@ public class HwvtepDeviceInfo {
         private final UUID uuid;
         private final Object data;
         private final DeviceDataStatus status;
+        private long intransitTimeStamp;
 
         DeviceData(InstanceIdentifier key, UUID uuid, Object data, DeviceDataStatus status) {
             this.data = data;
             this.key = key;
             this.status = status;
             this.uuid = uuid;
+            if (status == DeviceDataStatus.IN_TRANSIT) {
+                intransitTimeStamp = System.currentTimeMillis();
+            }
         }
 
         public Object getData() {
@@ -79,47 +107,78 @@ public class HwvtepDeviceInfo {
         public UUID getUuid() {
             return uuid;
         }
+
+        public InstanceIdentifier getKey() {
+            return key;
+        }
+
+        public boolean isIntransitTimeExpired() {
+            return System.currentTimeMillis()
+                    > intransitTimeStamp + HwvtepSouthboundConstants.IN_TRANSIT_STATE_EXPIRY_TIME_MILLIS;
+        }
+
+        public boolean isInTransitState() {
+            return status == DeviceDataStatus.IN_TRANSIT;
+        }
+
+        public boolean isAvailableInOperDs() {
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return key + " uuid:" + uuid + " data:" + data + " status:" + status;
+        }
     }
 
-    //TODO remove this
-    private Map<UUID, LogicalSwitch> logicalSwitches = null;
-    private Map<UUID, PhysicalSwitch> physicalSwitches = null;
-    private Map<UUID, PhysicalLocator> physicalLocators = null;
-    private Map<UUID, UUID> mapTunnelToPhysicalSwitch = null;
+    private static AtomicInteger ZERO = new AtomicInteger(0);
+    private final Map<InstanceIdentifier<?>, Set<InstanceIdentifier>> tepIdReferences = new ConcurrentHashMap<>();
+    private final Map<InstanceIdentifier<LogicalSwitches>, Map<InstanceIdentifier<RemoteUcastMacs>, RemoteUcastMacs>>
+            logicalSwitchVsUcasts = new ConcurrentHashMap<>();
+    private final Map<InstanceIdentifier<LogicalSwitches>, Map<InstanceIdentifier<RemoteMcastMacs>, RemoteMcastMacs>>
+            logicalSwitchVsMcasts = new ConcurrentHashMap<>();
+    private final Map<UUID, PhysicalSwitch> physicalSwitches = new ConcurrentHashMap<>();
+    private final Map<UUID, UUID> mapTunnelToPhysicalSwitch = new ConcurrentHashMap<>();
+
+    private final HwvtepConnectionInstance connectionInstance;
 
-    private HwvtepConnectionInstance connectionInstance;
+    private Map<InstanceIdentifier, AtomicInteger> iidInQueueCount = new ConcurrentHashMap<>();
+    private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> configKeyVsData =
+            new ConcurrentHashMap<>();
+    private final Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> opKeyVsData =
+            new ConcurrentHashMap<>();
+    private final Map<Class<? extends Identifiable>, Map<UUID, DeviceData>> uuidVsData = new ConcurrentHashMap<>();
+    private final DependencyQueue dependencyQueue;
+    private TransactionHistory controllerTxHistory;
+    private TransactionHistory deviceUpdateHistory;
 
-    private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> configKeyVsData = new ConcurrentHashMap<>();
-    private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> opKeyVsData = new ConcurrentHashMap<>();
-    private Map<Class<? extends Identifiable>, Map<UUID, Object>> uuidVsData = new ConcurrentHashMap<>();
-    private DependencyQueue dependencyQueue;
 
     public HwvtepDeviceInfo(HwvtepConnectionInstance hwvtepConnectionInstance) {
         this.connectionInstance = hwvtepConnectionInstance;
-        this.logicalSwitches = new HashMap<>();
-        this.physicalSwitches = new HashMap<>();
-        this.physicalLocators = new HashMap<>();
-        this.mapTunnelToPhysicalSwitch = new HashMap<>();
         this.dependencyQueue = new DependencyQueue(this);
     }
 
     public LogicalSwitch getLogicalSwitch(UUID uuid) {
-        return (LogicalSwitch) getDeviceOperData(LogicalSwitches.class, uuid);
+        DeviceData deviceData = getDeviceOperData(LogicalSwitches.class, uuid);
+        if (deviceData != null && deviceData.getData() != null) {
+            return (LogicalSwitch) deviceData.getData();
+        }
+        return null;
     }
 
     public Map<UUID, LogicalSwitch> getLogicalSwitches() {
-        Map<UUID, Object> switches = uuidVsData.get(LogicalSwitches.class);
+        Map<UUID, DeviceData> switches = uuidVsData.get(LogicalSwitches.class);
         Map<UUID, LogicalSwitch> result = new HashMap<>();
         if (switches != null) {
-            for (Map.Entry<UUID, Object> entry : switches.entrySet()) {
-                result.put(entry.getKey(), (LogicalSwitch) entry.getValue());
+            for (Map.Entry<UUID, DeviceData> entry : switches.entrySet()) {
+                result.put(entry.getKey(), (LogicalSwitch) entry.getValue().getData());
             }
         }
         return result;
     }
 
-    public void putPhysicalSwitch(UUID uuid, PhysicalSwitch pSwitch) {
-        physicalSwitches.put(uuid, pSwitch);
+    public void putPhysicalSwitch(UUID uuid, PhysicalSwitch physicalSwitch) {
+        physicalSwitches.put(uuid, physicalSwitch);
     }
 
     public PhysicalSwitch getPhysicalSwitch(UUID uuid) {
@@ -135,15 +194,19 @@ public class HwvtepDeviceInfo {
     }
 
     public PhysicalLocator getPhysicalLocator(UUID uuid) {
-        return (PhysicalLocator) getDeviceOperData(TerminationPoint.class, uuid);
+        DeviceData deviceData = getDeviceOperData(TerminationPoint.class, uuid);
+        if (deviceData != null && deviceData.getData() != null) {
+            return (PhysicalLocator) deviceData.getData();
+        }
+        return null;
     }
 
     public Map<UUID, PhysicalLocator> getPhysicalLocators() {
-        Map<UUID, Object> locators = uuidVsData.get(LogicalSwitches.class);
+        Map<UUID, DeviceData> locators = uuidVsData.get(TerminationPoint.class);
         Map<UUID, PhysicalLocator> result = new HashMap<>();
         if (locators != null) {
-            for (Map.Entry<UUID, Object> entry : locators.entrySet()) {
-                result.put(entry.getKey(), (PhysicalLocator) entry.getValue());
+            for (Map.Entry<UUID, DeviceData> entry : locators.entrySet()) {
+                result.put(entry.getKey(), (PhysicalLocator) entry.getValue().getData());
             }
         }
         return result;
@@ -179,10 +242,14 @@ public class HwvtepDeviceInfo {
                 new DeviceData(key, null, data, DeviceDataStatus.AVAILABLE));
     }
 
-    public Object getConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+    public DeviceData getConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
         return HwvtepSouthboundUtil.getData(configKeyVsData, cls, key);
     }
 
+    public Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> getConfigData() {
+        return Collections.unmodifiableMap(configKeyVsData);
+    }
+
     public void clearConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
         HwvtepSouthboundUtil.clearData(configKeyVsData, cls, key);
     }
@@ -200,11 +267,12 @@ public class HwvtepDeviceInfo {
                 new DeviceData(key, uuid, data, DeviceDataStatus.IN_TRANSIT));
     }
 
-    public void updateDeviceOperData(Class<? extends Identifiable> cls, InstanceIdentifier key, UUID uuid, Object data) {
+    public void updateDeviceOperData(Class<? extends Identifiable> cls, InstanceIdentifier key,
+            UUID uuid, Object data) {
         LOG.debug("Updating device data {}", key);
-        HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key,
-                new DeviceData(key, uuid, data, DeviceDataStatus.AVAILABLE));
-        HwvtepSouthboundUtil.updateData(uuidVsData, cls, uuid, data);
+        DeviceData deviceData = new DeviceData(key, uuid, data, DeviceDataStatus.AVAILABLE);
+        HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key, deviceData);
+        HwvtepSouthboundUtil.updateData(uuidVsData, cls, uuid, deviceData);
     }
 
     public void clearDeviceOperData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
@@ -215,7 +283,30 @@ public class HwvtepDeviceInfo {
         HwvtepSouthboundUtil.clearData(opKeyVsData, cls, key);
     }
 
-    public Object getDeviceOperData(Class<? extends Identifiable> cls, UUID uuid) {
+    public void clearDeviceOperData(Class<? extends Identifiable> cls) {
+        Map<InstanceIdentifier, DeviceData> iids = opKeyVsData.get(cls);
+        if (iids != null && !iids.isEmpty()) {
+            Iterator<Map.Entry<InstanceIdentifier, DeviceData>> it = iids.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry<InstanceIdentifier, DeviceData> entry = it.next();
+                DeviceData deviceData = entry.getValue();
+                if (deviceData != null && deviceData.getStatus() != DeviceDataStatus.IN_TRANSIT) {
+                    it.remove();
+                }
+            }
+        }
+    }
+
+    public void clearDeviceOperUUID(Class<? extends Identifiable> cls, InstanceIdentifier key, UUID uuid) {
+        LOG.debug("Clearing device data {}", key);
+        if (uuidVsData.containsKey(cls) && uuidVsData.get(cls).containsKey(uuid)) {
+            LOG.debug("Remove {} {} from device data.", connectionInstance.getNodeId().getValue(), cls.getSimpleName());
+        }
+        HwvtepSouthboundUtil.clearData(uuidVsData, cls, uuid);
+        HwvtepSouthboundUtil.clearData(opKeyVsData, cls, key);
+    }
+
+    public DeviceData getDeviceOperData(Class<? extends Identifiable> cls, UUID uuid) {
         return HwvtepSouthboundUtil.getData(uuidVsData, cls, uuid);
     }
 
@@ -223,6 +314,18 @@ public class HwvtepDeviceInfo {
         return HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
     }
 
+    public Map<InstanceIdentifier, DeviceData> getDeviceOperData(Class<? extends Identifiable> cls) {
+        return opKeyVsData.get(cls);
+    }
+
+    public InstanceIdentifier getDeviceOperKey(final Class<? extends Identifiable> cls, final UUID uuid) {
+        DeviceData deviceData = HwvtepSouthboundUtil.getData(uuidVsData, cls, uuid);
+        if (deviceData != null) {
+            return deviceData.getKey();
+        }
+        return null;
+    }
+
     public UUID getUUID(Class<? extends Identifiable> cls, InstanceIdentifier key) {
         DeviceData data = HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
         if (data != null) {
@@ -239,30 +342,154 @@ public class HwvtepDeviceInfo {
         dependencyQueue.processReadyJobsFromConfigQueue(connectionInstance);
     }
 
-    public void onOperDataAvailable() {
+    public synchronized void onOperDataAvailable() {
         dependencyQueue.processReadyJobsFromOpQueue(connectionInstance);
     }
 
     public void scheduleTransaction(final TransactCommand transactCommand) {
-        dependencyQueue.submit(new Runnable() {
-            @Override
-            public void run() {
-                connectionInstance.transact(transactCommand);
+        dependencyQueue.submit(() -> connectionInstance.transact(transactCommand));
+    }
+
+    public void clearInTransit(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+        DeviceData deviceData = getDeviceOperData(cls, key);
+        if (deviceData != null && deviceData.isInTransitState()) {
+            if (deviceData.getData() != null) {
+                HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key,
+                        new DeviceData(key, deviceData.getUuid(), deviceData.getData(), DeviceDataStatus.AVAILABLE));
+            } else {
+                clearDeviceOperData(cls, key);
             }
-        });
+        }
     }
 
-    public void clearInTransitData() {
-        //TODO restore old data
-        for (Map<InstanceIdentifier, DeviceData> map : opKeyVsData.values()) {
-            Iterator<Map.Entry<InstanceIdentifier, DeviceData>> iterator = map.entrySet().iterator();
-            while ( iterator.hasNext() ) {
-                Map.Entry<InstanceIdentifier, DeviceData> entry = iterator.next();
-                if (entry.getValue().getStatus() == DeviceDataStatus.IN_TRANSIT) {
-                    iterator.remove();
-                }
+    public void incRefCount(InstanceIdentifier reference, InstanceIdentifier tep) {
+        if (reference == null || tep == null) {
+            return;
+        }
+        tepIdReferences.computeIfAbsent(tep, (tepId) -> Sets.newConcurrentHashSet());
+        tepIdReferences.get(tep).add(reference);
+    }
+
+    public int getRefCount(InstanceIdentifier tep) {
+        return tepIdReferences.containsKey(tep) ? tepIdReferences.get(tep).size() : 0;
+    }
+
+    public Set<InstanceIdentifier> getRefCounts(InstanceIdentifier tep) {
+        return tepIdReferences.get(tep);
+    }
+
+    public void decRefCount(InstanceIdentifier reference, InstanceIdentifier tep) {
+        if (reference == null || tep == null || !tepIdReferences.containsKey(tep)) {
+            return;
+        }
+        //synchronize to make sure that no two parallel deletes puts the key in transit state twice
+        synchronized (this) {
+            boolean removed = tepIdReferences.get(tep).remove(reference);
+            if (removed && tepIdReferences.get(tep).isEmpty()) {
+                LOG.debug("Marking the termination point as in transit ref count zero {} ", tep);
+                markKeyAsInTransit(TerminationPoint.class, tep);
             }
         }
-        onOperDataAvailable();
     }
+
+    public void clearLogicalSwitchRefs(InstanceIdentifier<LogicalSwitches> logicalSwitchKey) {
+        Map<InstanceIdentifier<RemoteMcastMacs>, RemoteMcastMacs> mcasts = logicalSwitchVsMcasts.get(logicalSwitchKey);
+        if (mcasts != null) {
+            mcasts.entrySet().forEach((entry) -> removeRemoteMcast(logicalSwitchKey, entry.getKey()));
+        }
+        Map<InstanceIdentifier<RemoteUcastMacs>, RemoteUcastMacs> ucasts = logicalSwitchVsUcasts.get(logicalSwitchKey);
+        if (ucasts != null) {
+            ucasts.entrySet().forEach((entry) -> removeRemoteUcast(logicalSwitchKey, entry.getKey()));
+        }
+        markKeyAsInTransit(LogicalSwitches.class, logicalSwitchKey);
+    }
+
+    public  void updateRemoteMcast(InstanceIdentifier<LogicalSwitches> lsIid,
+                                   InstanceIdentifier<RemoteMcastMacs> mcastIid,
+                                   RemoteMcastMacs mac) {
+        logicalSwitchVsMcasts.computeIfAbsent(lsIid, (lsKey) -> new ConcurrentHashMap<>());
+        logicalSwitchVsMcasts.get(lsIid).put(mcastIid, mac);
+        if (mac.getLocatorSet() != null) {
+            mac.getLocatorSet().forEach((iid) -> incRefCount(mcastIid, iid.getLocatorRef().getValue()));
+        }
+    }
+
+    public  void updateRemoteUcast(InstanceIdentifier<LogicalSwitches> lsIid,
+                                   InstanceIdentifier<RemoteUcastMacs> ucastIid,
+                                   RemoteUcastMacs mac) {
+        logicalSwitchVsUcasts.computeIfAbsent(lsIid, (lsKey) -> new ConcurrentHashMap<>());
+        logicalSwitchVsUcasts.get(lsIid).put(ucastIid, mac);
+        incRefCount(ucastIid, mac.getLocatorRef().getValue());
+    }
+
+    public void removeRemoteMcast(InstanceIdentifier<LogicalSwitches> lsIid,
+            InstanceIdentifier<RemoteMcastMacs> mcastIid) {
+        if (!logicalSwitchVsMcasts.containsKey(lsIid)) {
+            return;
+        }
+        RemoteMcastMacs mac = logicalSwitchVsMcasts.get(lsIid).remove(mcastIid);
+        if (mac != null && mac.getLocatorSet() != null) {
+            mac.getLocatorSet().forEach((iid) -> decRefCount(mcastIid, iid.getLocatorRef().getValue()));
+        }
+        markKeyAsInTransit(RemoteMcastMacs.class, mcastIid);
+    }
+
+    public void removeRemoteUcast(InstanceIdentifier<LogicalSwitches> lsIid,
+                                   InstanceIdentifier<RemoteUcastMacs> ucastIid) {
+        if (!logicalSwitchVsUcasts.containsKey(lsIid)) {
+            return;
+        }
+        RemoteUcastMacs mac = logicalSwitchVsUcasts.get(lsIid).remove(ucastIid);
+        if (mac != null) {
+            decRefCount(ucastIid, mac.getLocatorRef().getValue());
+        }
+        markKeyAsInTransit(RemoteUcastMacs.class, ucastIid);
+    }
+
+    public HwvtepConnectionInstance getConnectionInstance() {
+        return connectionInstance;
+    }
+
+    public void setConfigKeyVsData(Map<Class<? extends Identifiable>, Map<InstanceIdentifier,
+            DeviceData>> configKeyVsData) {
+        this.configKeyVsData = configKeyVsData;
+    }
+
+    public void setControllerTxHistory(TransactionHistory controllerTxHistory) {
+        this.controllerTxHistory = controllerTxHistory;
+    }
+
+    public void setDeviceUpdateHistory(TransactionHistory deviceUpdateHistory) {
+        this.deviceUpdateHistory = deviceUpdateHistory;
+    }
+
+    public void addToControllerTx(TransactionType transactionType, Object object) {
+        controllerTxHistory.addToHistory(transactionType, object);
+    }
+
+    public void addToDeviceUpdate(TransactionType transactionType, Object object) {
+        deviceUpdateHistory.addToHistory(transactionType, object);
+    }
+
+    public Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> getOperData() {
+        return Collections.unmodifiableMap(opKeyVsData);
+    }
+
+    public Map<Class<? extends Identifiable>, Map<UUID, DeviceData>> getUuidData() {
+        return Collections.unmodifiableMap(uuidVsData);
+    }
+
+    public void putKeyInDependencyQueue(InstanceIdentifier iid) {
+        iidInQueueCount.putIfAbsent(iid, new AtomicInteger(0));
+        iidInQueueCount.get(iid).incrementAndGet();
+    }
+
+    public void clearKeyFromDependencyQueue(InstanceIdentifier iid) {
+        iidInQueueCount.remove(iid);
+    }
+
+    public boolean isKeyInDependencyQueue(InstanceIdentifier iid) {
+        return iidInQueueCount.containsKey(iid);
+    }
+
 }