* 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;
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
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,
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() {
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) {
}
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;
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);
}
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) {
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);
}
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) {
dependencyQueue.processReadyJobsFromConfigQueue(connectionInstance);
}
- public void onOperDataAvailable() {
+ public synchronized void onOperDataAvailable() {
dependencyQueue.processReadyJobsFromOpQueue(connectionInstance);
}
dependencyQueue.submit(() -> connectionInstance.transact(transactCommand));
}
- 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 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 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);
+ }
+
}