Enhance the McastMacsRemoteUpdateCommand to get the uuid from the device if not prese... 42/89042/5
authorChandra Shekar S <chandra.shekar.s@ericsson.com>
Mon, 13 Apr 2020 10:57:47 +0000 (16:27 +0530)
committerChetan Arakere Gowdru <chetan.arakere@altencalsoftlabs.com>
Mon, 20 Apr 2020 05:14:34 +0000 (05:14 +0000)
This review is to :
1. Enhance the McastMacsRemoteUpdateCommand to get the uuid from the device if not present in cache
2. Minor refactors on the MacsCommands

Signed-off-by: Chandra Shekar S <chandra.shekar.s@ericsson.com>
Change-Id: I73f6114cacfd86c59301f098f4338125c32dc65d

hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepTableReader.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/McastMacsRemoteRemoveCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/McastMacsRemoteUpdateCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalPortUpdateCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/UcastMacsRemoteRemoveCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/UcastMacsRemoteUpdateCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/DataChangeListenerTestBase.java

index 0ecb0e281131e34daa5d79582f4532eb7d256715..9402402278633cb546b63b9cb95a21b9d960fca6 100644 (file)
@@ -60,6 +60,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hw
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
 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.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
 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.DataObject;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
@@ -94,7 +95,8 @@ public class HwvtepTableReader {
         RemoteMcastMacs.class, McastMacsRemote.class,
         RemoteUcastMacs.class, UcastMacsRemote.class,
         LogicalSwitches.class, LogicalSwitch.class,
-        TerminationPoint.class, PhysicalLocator.class);
+        TerminationPoint.class, PhysicalLocator.class,
+        VlanBindings.class, PhysicalPort.class);
 
     private final ImmutableMap<Class<? extends Identifiable<?>>, WhereClauseGetter<?>> whereClauseGetters;
     private final ImmutableClassToInstanceMap<TypedBaseTable<?>> tables;
@@ -135,6 +137,10 @@ public class HwvtepTableReader {
                 tableBuilder.put(PhysicalLocator.class, plTable);
                 whereBuilder.put(TerminationPoint.class, new LocatorWhereClauseGetter(plTable));
             }
+            final PhysicalPort physicalPort = dbSchema.getTypedRowWrapper(PhysicalPort.class, null);
+            if (physicalPort != null) {
+                tableBuilder.put(PhysicalPort.class, physicalPort);
+            }
         }
 
         tables = tableBuilder.build();
@@ -158,19 +164,30 @@ public class HwvtepTableReader {
             RemoteMcastMacsKey key = iid.firstKeyOf(RemoteMcastMacs.class);
             InstanceIdentifier<LogicalSwitches> lsIid = (InstanceIdentifier<LogicalSwitches>) key.getLogicalSwitchRef()
                     .getValue();
-            UUID lsUUID = connectionInstance.getDeviceInfo().getUUID(LogicalSwitches.class, lsIid);
+            UUID lsUUID = getLsUuid(lsIid);
             if (lsUUID == null) {
-                LOG.error("Could not find uuid for ls key {}", lsIid);
+                LOG.warn("Could not find uuid for ls key {}", lsIid);
                 return null;
             }
 
             ArrayList<Condition> conditions = new ArrayList<>();
             conditions.add(macTable.getLogicalSwitchColumn().getSchema().opEqual(lsUUID));
-            conditions.add(macTable.getMacColumn().getSchema().opEqual(key.getMacEntryKey().getValue()));
             return conditions;
         }
     }
 
+    public UUID getLsUuid(InstanceIdentifier lsIid) {
+        UUID lsUUID = connectionInstance.getDeviceInfo().getUUID(LogicalSwitches.class, lsIid);
+        if (lsUUID == null) {
+            Optional<TypedBaseTable> optional =
+                    getHwvtepTableEntryUUID(LogicalSwitches.class, lsIid, null);
+            if (optional.isPresent()) {
+                lsUUID = optional.get().getUuid();
+            }
+        }
+        return lsUUID;
+    }
+
     class RemoteUcastMacWhereClauseGetter implements WhereClauseGetter<RemoteUcastMacs> {
         private final UcastMacsRemote macTable;
 
index 2c7024bff3f54d49f49f23f08ab89396eaa6717d..08cdca33f3fcc2bf50943399268fb69b738c3d52 100644 (file)
@@ -91,24 +91,40 @@ public class McastMacsRemoteRemoveCommand extends AbstractTransactCommand<Remote
                                     final RemoteMcastMacs mac,
                                     final InstanceIdentifier macIid,
                                     final Object... extraData) {
-        LOG.debug("Removing remoteMcastMacs, mac address: {}", mac.getMacEntryKey().getValue());
         clearConfigData(RemoteMcastMacs.class, macIid);
-        HwvtepDeviceInfo.DeviceData operationalMacOptional =
-                getDeviceInfo().getDeviceOperData(RemoteMcastMacs.class, macIid);
+        long transactionId = getOperationalState().getTransactionId();
+        LOG.debug("Remove received for RemoteMcastMacs key: {} txId: {}", macIid, transactionId);
+        HwvtepDeviceInfo.DeviceData deviceData = getDeviceOpData(RemoteMcastMacs.class, macIid);
         McastMacsRemote mcastMacsRemote = transaction.getTypedRowSchema(McastMacsRemote.class);
-        if (operationalMacOptional != null && operationalMacOptional.getUuid() != null) {
-            //when mac entry is deleted, its referenced locator set and locators are deleted automatically.
-            //TODO: locator in config DS is not deleted
-            UUID macEntryUUID = operationalMacOptional.getUuid();
-            mcastMacsRemote.getUuidColumn().setData(macEntryUUID);
-            transaction.add(op.delete(mcastMacsRemote.getSchema())
-                    .where(mcastMacsRemote.getUuidColumn().getSchema().opEqual(macEntryUUID)).build());
-            transaction.add(op.comment("McastMacRemote: Deleting " + mac.getMacEntryKey().getValue()));
-            updateCurrentTxDeleteData(RemoteMcastMacs.class, macIid, mac);
-            updateControllerTxHistory(TransactionType.DELETE, mcastMacsRemote);
-        } else {
-            LOG.warn("Unable to delete remoteMcastMacs {} because it was not found in the operational store",
-                    mac.getMacEntryKey().getValue());
+        boolean deleted = false;
+        if (deviceData != null && deviceData.getData() != null && deviceData.getData() instanceof McastMacsRemote
+                && ((McastMacsRemote)deviceData.getData()).getLogicalSwitchColumn() != null) {
+            UUID logicalSwitchUid = ((McastMacsRemote)deviceData.getData()).getLogicalSwitchColumn().getData();
+            if (logicalSwitchUid != null) {
+                transaction.add(op.delete(mcastMacsRemote.getSchema())
+                        .where(mcastMacsRemote.getLogicalSwitchColumn().getSchema().opEqual(logicalSwitchUid)).build());
+                deleted = true;
+                updateCurrentTxDeleteData(RemoteMcastMacs.class, macIid, mac);
+                updateControllerTxHistory(TransactionType.DELETE, new StringBuilder(mcastMacsRemote.toString())
+                        .append(":  LS: ").append(logicalSwitchUid));
+                LOG.info("CONTROLLER - {} {} LS:{}", TransactionType.DELETE, mcastMacsRemote, logicalSwitchUid);
+            }
+        }
+        if (!deleted && deviceData != null) {
+            UUID macEntryUUID = deviceData.getUuid();
+            if (macEntryUUID != null) {
+                mcastMacsRemote.getUuidColumn().setData(macEntryUUID);
+                updateCurrentTxDeleteData(RemoteMcastMacs.class, macIid, mac);
+                transaction.add(op.delete(mcastMacsRemote.getSchema())
+                        .where(mcastMacsRemote.getUuidColumn().getSchema().opEqual(macEntryUUID)).build());
+                updateControllerTxHistory(TransactionType.DELETE, new StringBuilder(mcastMacsRemote.toString())
+                        .append(":  Mac : ").append(macEntryUUID));
+                LOG.info("CONTROLLER - {} {} Mac :{}", TransactionType.DELETE, mcastMacsRemote, macEntryUUID);
+            } else {
+                LOG.error("Failed to delete remote mcast entry as it is not found in device {}", macIid);
+                getDeviceInfo().clearConfigData(RemoteMcastMacs.class, macIid);
+                return;
+            }
         }
     }
 
index 78f00a43edfee1683b1fb105059a7ddafed75f5a..49ae4de2d3520f44c7b607268ffe7ddef828b293 100644 (file)
@@ -9,6 +9,8 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -17,6 +19,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Set;
+
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
@@ -86,38 +90,38 @@ public class McastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
                                        final RemoteMcastMacs mac,
                                        final InstanceIdentifier macKey,
                                        final Object... extraData) {
-        LOG.debug("Creating remoteMcastMacs, mac address: {}", mac.getMacEntryKey().getValue());
-        final HwvtepDeviceInfo.DeviceData operationalMacOptional =
-                getDeviceInfo().getDeviceOperData(RemoteMcastMacs.class, macKey);
+
+        String nodeId = instanceIdentifier.firstKeyOf(Node.class).getNodeId().getValue();
+        LOG.debug("Creating remoteMcastMacs, mac address: {} {}", nodeId, mac.getMacEntryKey().getValue());
+
         McastMacsRemote mcastMacsRemote = transaction.getTypedRowWrapper(McastMacsRemote.class);
         setIpAddress(mcastMacsRemote, mac);
-        setLocatorSet(transaction, mcastMacsRemote, mac);
         setLogicalSwitch(transaction, mcastMacsRemote, mac);
-        if (operationalMacOptional == null) {
-            setMac(mcastMacsRemote, mac);
-            LOG.trace("execute: create RemoteMcastMac entry: {}", mcastMacsRemote);
+        setMac(mcastMacsRemote, mac);
+        InstanceIdentifier<RemoteMcastMacs> macIid = instanceIdentifier.augmentation(HwvtepGlobalAugmentation.class)
+                .child(RemoteMcastMacs.class, mac.key());
+        HwvtepDeviceInfo.DeviceData deviceData = super.fetchDeviceData(RemoteMcastMacs.class, macIid);
+        if (deviceData == null) {
+            setLocatorSet(transaction, mcastMacsRemote, mac);
             transaction.add(op.insert(mcastMacsRemote));
-            transaction.add(op.comment("McastMacRemote: Creating " + mac.getMacEntryKey().getValue()));
-            updateCurrentTxData(RemoteMcastMacs.class, macKey, TXUUID, mac);
+            updateCurrentTxData(RemoteMcastMacs.class, macIid, new UUID("uuid"), mac);
             updateControllerTxHistory(TransactionType.ADD, mcastMacsRemote);
-        } else if (operationalMacOptional.getUuid() != null) {
-            UUID macEntryUUID = operationalMacOptional.getUuid();
+            LOG.info("CONTROLLER - {} {}", TransactionType.ADD, mcastMacsRemote);
+        } else if (deviceData.getUuid() != null) {
+            setLocatorSet(transaction, mcastMacsRemote, mac);
+            UUID macEntryUUID = deviceData.getUuid();
             McastMacsRemote extraMac = transaction.getTypedRowSchema(McastMacsRemote.class);
             extraMac.getUuidColumn().setData(macEntryUUID);
-            LOG.trace("execute: update RemoteMcastMac entry: {}", mcastMacsRemote);
             transaction.add(op.update(mcastMacsRemote)
                     .where(extraMac.getUuidColumn().getSchema().opEqual(macEntryUUID))
                     .build());
-            transaction.add(op.comment("McastMacRemote: Updating " + macEntryUUID));
             updateControllerTxHistory(TransactionType.UPDATE, mcastMacsRemote);
-            //add to updates so that tep ref counts can be updated upon success
-            addToUpdates(macKey, mac);
+            LOG.info("CONTROLLER - {} {}", TransactionType.UPDATE, mcastMacsRemote);
+            addToUpdates(macIid, mac);
         } else {
-            LOG.warn("Unable to update remoteMcastMacs {} because uuid not found in the operational store",
-                    mac.getMacEntryKey().getValue());
+            LOG.error("Unable to update remoteMcastMacs {} {} because uuid not found in the operational"
+                    + " store txId: {}", mac, deviceData, getOperationalState().getTransactionId());
         }
-        InstanceIdentifier<RemoteMcastMacs> macIid = instanceIdentifier.augmentation(HwvtepGlobalAugmentation.class)
-                .child(RemoteMcastMacs.class, mac.key());
         updateConfigData(RemoteMcastMacs.class, macIid, mac);
     }
 
@@ -127,8 +131,10 @@ public class McastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
             @SuppressWarnings("unchecked")
             InstanceIdentifier<LogicalSwitches> lswitchIid =
                     (InstanceIdentifier<LogicalSwitches>) inputMac.getLogicalSwitchRef().getValue();
-            mcastMacsRemote.setLogicalSwitch(TransactUtils.getLogicalSwitchUUID(transaction,
-                    getOperationalState(), lswitchIid));
+            UUID logicalSwitchUUID = TransactUtils.getLogicalSwitchUUID(transaction, getOperationalState(), lswitchIid);
+            if (logicalSwitchUUID != null) {
+                mcastMacsRemote.setLogicalSwitch(logicalSwitchUUID);
+            }
         }
     }
 
@@ -164,7 +170,27 @@ public class McastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
 
     @Override
     protected boolean areEqual(final RemoteMcastMacs macs1, final RemoteMcastMacs macs2) {
-        return macs1.key().equals(macs2.key()) && Objects.equals(macs1.getLocatorSet(), macs2.getLocatorSet());
+        if (getOperationalState().isInReconciliation()) {
+            return Objects.equals(macs1.key(), macs2.key())
+                    && compareLocatorSets(macs1.getLocatorSet(), macs2.getLocatorSet());
+        }
+        return Objects.equals(macs1.key(), macs2.key())
+                && Objects.equals(macs1.getLocatorSet(), macs2.getLocatorSet());
+    }
+
+    private boolean compareLocatorSets(List<LocatorSet> locatorSet1, List<LocatorSet> locatorSet2) {
+        if (locatorSet1 == null) {
+            locatorSet1 = Collections.EMPTY_LIST;
+        }
+        if (locatorSet2 == null) {
+            locatorSet2 = Collections.EMPTY_LIST;
+        }
+        if (locatorSet1.size() != locatorSet2.size()) {
+            return false;
+        }
+        Set set1 = Sets.newHashSet(locatorSet1);
+        Set set2 = Sets.newHashSet(locatorSet2);
+        return set1.containsAll(set2);
     }
 
     static class McastMacUnMetDependencyGetter extends UnMetDependencyGetter<RemoteMcastMacs> {
@@ -172,15 +198,15 @@ public class McastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
         @Override
         public List<InstanceIdentifier<?>> getLogicalSwitchDependencies(final RemoteMcastMacs data) {
             if (data == null) {
-                return Collections.emptyList();
+                return Collections.EMPTY_LIST;
             }
-            return Collections.singletonList(data.getLogicalSwitchRef().getValue());
+            return Lists.newArrayList(data.getLogicalSwitchRef().getValue());
         }
 
         @Override
         public List<InstanceIdentifier<?>> getTerminationPointDependencies(final RemoteMcastMacs data) {
             if (data == null || HwvtepSouthboundUtil.isEmpty(data.getLocatorSet())) {
-                return Collections.emptyList();
+                return Collections.EMPTY_LIST;
             }
             List<InstanceIdentifier<?>> locators = new ArrayList<>();
             for (LocatorSet locator: data.getLocatorSet()) {
index a23a26aa6d4887315abcd2bd7f6c7b182f527f01..6ce7e7726b6c503633ce94be711451321adf4880 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
-import com.google.common.collect.Lists;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -18,27 +17,28 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
+
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
 import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalPort;
 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
 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.physical.port.attributes.VlanBindings;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindingsKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class PhysicalPortUpdateCommand extends AbstractTransactCommand {
+public class PhysicalPortUpdateCommand extends AbstractTransactCommand<TerminationPoint, PhysicalSwitchAugmentation> {
     private static final Logger LOG = LoggerFactory.getLogger(PhysicalPortUpdateCommand.class);
     private static final VlanBindingsUnMetDependencyGetter DEPENDENCY_GETTER = new VlanBindingsUnMetDependencyGetter();
 
@@ -70,36 +70,98 @@ public class PhysicalPortUpdateCommand extends AbstractTransactCommand {
     public void updatePhysicalPort(final TransactionBuilder transaction,
                                    final InstanceIdentifier<Node> psNodeiid,
                                    final List<TerminationPoint> listPort) {
-        //Get physical switch which the port belong to: in operation DS or new created
-        for (TerminationPoint tp : listPort) {
-            HwvtepPhysicalPortAugmentation port = tp.augmentation(HwvtepPhysicalPortAugmentation.class);
-            LOG.debug("Creating a physical port named: {}", port.getHwvtepNodeName().getValue());
-            InstanceIdentifier<TerminationPoint> key = getTpIid(psNodeiid, port.getHwvtepNodeName().getValue());
+        if (listPort != null) {
+            for (TerminationPoint port : listPort) {
+                LOG.debug("Processing port {}", port);
+                InstanceIdentifier<TerminationPoint> tpIId = psNodeiid.child(TerminationPoint.class, port.key());
+                HwvtepPhysicalPortAugmentation hwvtepPhysicalPortAugmentation =
+                        port.augmentation(HwvtepPhysicalPortAugmentation.class);
+                if (hwvtepPhysicalPortAugmentation != null) {
+                    onConfigUpdate(transaction, psNodeiid, port, tpIId);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onConfigUpdate(TransactionBuilder transaction, InstanceIdentifier psNodeiid,
+                               TerminationPoint port, InstanceIdentifier tpIId, Object... extraData) {
+        doDeviceTransaction(transaction, psNodeiid, port, tpIId);
+    }
 
-            getOperationalState().getDeviceInfo().updateConfigData(VlanBindings.class, key, tp);
-            HwvtepDeviceInfo.DeviceData deviceOperdata = getDeviceInfo().getDeviceOperData(VlanBindings.class, key);
-            if (deviceOperdata == null || deviceOperdata.getData() == null) {
-                LOG.error("Updated the device oper cache for port from actual device {}", key);
-                deviceOperdata = super.fetchDeviceData(VlanBindings.class, key);
+    @Override
+    public void doDeviceTransaction(TransactionBuilder transaction, InstanceIdentifier nodeIid,
+                                    TerminationPoint data, InstanceIdentifier key, Object... extraData) {
+        LOG.debug("Processing port doDeviceTransaction {}", data);
+        InstanceIdentifier<Node> psNodeiid = nodeIid;
+        HwvtepPhysicalPortAugmentation port = ((TerminationPoint)data).augmentation(
+                HwvtepPhysicalPortAugmentation.class);
+        if (port == null) {
+            LOG.info("No port augmentation found for port {}", data);
+            return;
+        }
+        if (port.getHwvtepNodeName() == null) {
+            LOG.info("No port hwvtep node name found for port {}", data);
+            return;
+        }
+        LOG.debug("Creating a physical port named: {}", port.getHwvtepNodeName().getValue());
+        getOperationalState().getDeviceInfo().updateConfigData(VlanBindings.class, key, data);
+        HwvtepDeviceInfo.DeviceData deviceData = getOperationalState().getDeviceInfo()
+                .getDeviceOperData(VlanBindings.class, key);
+        PhysicalPort physicalPort = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
+                PhysicalPort.class);
+        //get managing global node of physicalSwitchBelong
+        setName(physicalPort, port);
+        setDescription(physicalPort, port);
+        if (deviceData == null || deviceData.getData() == null) {
+            LOG.error("Updated the device oper cache for port from actual device {}", key);
+            deviceData = super.fetchDeviceData(VlanBindings.class, key);
+        }
+        if (deviceData == null || deviceData.getData() == null) {
+            LOG.warn("Port not present in opdata store {}", key);
+        } else {
+            if (deviceData.getData() == null || !(deviceData.getData() instanceof PhysicalPort)) {
+                LOG.error("Failed to get the device data for port {}", key);
             }
-            if (deviceOperdata == null || deviceOperdata.getData() == null) {
-                //create a physical port always happens from device
-                LOG.error("Physical port {} not present in oper datastore", port.getHwvtepNodeName().getValue());
-            } else {
-                PhysicalPort physicalPort = transaction.getTypedRowWrapper(PhysicalPort.class);
-                physicalPort.setName(port.getHwvtepNodeName().getValue());
-                setVlanBindings(psNodeiid, physicalPort, tp, transaction);
-                setDescription(physicalPort, port);
-                String existingPhysicalPortName = port.getHwvtepNodeName().getValue();
-                PhysicalPort extraPhyscialPort = transaction.getTypedRowWrapper(PhysicalPort.class);
-                extraPhyscialPort.setName("");
-                LOG.trace("execute: updating physical port: {}", physicalPort);
-                transaction.add(op.update(physicalPort)
-                        .where(extraPhyscialPort.getNameColumn().getSchema().opEqual(existingPhysicalPortName))
-                        .build());
-                transaction.add(op.comment("Physical Port: Updating " + existingPhysicalPortName));
-                updateControllerTxHistory(TransactionType.UPDATE, physicalPort);
+            Map<Long, UUID> bindingMap = setVlanBindings(nodeIid, physicalPort, data, key, transaction);
+            PhysicalPort tp = (PhysicalPort) deviceData.getData();
+            if (getOperationalState().isInReconciliation()) {
+                if (tp.getVlanBindingsColumn() != null && tp.getVlanBindingsColumn().getData() != null) {
+                    Map<Long, UUID> existing = new HashMap<>(tp.getVlanBindingsColumn().getData());
+                    if (existing.size() == bindingMap.size()) {
+                        boolean allMatched = bindingMap.entrySet().stream().allMatch(newEntry -> {
+                            return Objects.equals(existing.get(newEntry.getKey()), newEntry.getValue());
+                        });
+                        if (allMatched) {
+                            return;
+                        }
+                    }
+                }
             }
+            String nodeId = psNodeiid.firstKeyOf(Node.class).getNodeId().getValue();
+            getOperationalState().getDeviceInfo().updateDeviceOperData(VlanBindings.class, key,
+                    deviceData.getUuid(), deviceData.getData());
+            //updated physical port only
+
+            String existingPhysicalPortName = tp.getName();
+            PhysicalPort extraPhyscialPort =
+                    TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), PhysicalPort.class);
+            extraPhyscialPort.setName("");
+            LOG.trace("execute: updating physical port: {} {}", nodeId, physicalPort);
+            transaction.add(op.update(physicalPort)
+                    .where(extraPhyscialPort.getNameColumn().getSchema().opEqual(existingPhysicalPortName))
+                    .build());
+            transaction.add(op.comment("Physical Port: Updating " + existingPhysicalPortName));
+            updateControllerTxHistory(TransactionType.UPDATE, physicalPort);
+            LOG.info("CONTROLLER - {} {}", TransactionType.UPDATE, physicalPort);
+
+        }
+        return;
+    }
+
+    private void setName(PhysicalPort physicalPort, HwvtepPhysicalPortAugmentation inputPhysicalPort) {
+        if (inputPhysicalPort.getHwvtepNodeName() != null) {
+            physicalPort.setName(inputPhysicalPort.getHwvtepNodeName().getValue());
         }
     }
 
@@ -110,16 +172,17 @@ public class PhysicalPortUpdateCommand extends AbstractTransactCommand {
         }
     }
 
-    private void setVlanBindings(final InstanceIdentifier<Node> psNodeiid,
-                                 final PhysicalPort physicalPort,
-                                 final TerminationPoint tp,
-                                 final TransactionBuilder transaction) {
-        HwvtepPhysicalPortAugmentation inputPhysicalPort = tp.augmentation(HwvtepPhysicalPortAugmentation.class);
-        if (inputPhysicalPort.getVlanBindings() != null) {
+    private Map<Long, UUID> setVlanBindings(final InstanceIdentifier<Node> psNodeiid,
+                                            final PhysicalPort physicalPort,
+                                            final TerminationPoint inputPhysicalPort,
+                                            final InstanceIdentifier key,
+                                            final TransactionBuilder transaction) {
+        HwvtepPhysicalPortAugmentation portAugmentation = inputPhysicalPort.augmentation(
+                HwvtepPhysicalPortAugmentation.class);
+        Map<Long, UUID> bindingMap = new HashMap<>();
+        if (portAugmentation.getVlanBindings() != null) {
             //get UUID by LogicalSwitchRef
-            Map<Long, UUID> bindingMap = new HashMap<>();
-            for (VlanBindings vlanBinding: inputPhysicalPort.getVlanBindings()) {
-                InstanceIdentifier<VlanBindings> vlanIid = getVlanBindingIid(psNodeiid, physicalPort, vlanBinding);
+            for (VlanBindings vlanBinding : portAugmentation.getVlanBindings()) {
                 @SuppressWarnings("unchecked")
                 InstanceIdentifier<LogicalSwitches> lswitchIid =
                         (InstanceIdentifier<LogicalSwitches>) vlanBinding.getLogicalSwitchRef().getValue();
@@ -130,13 +193,11 @@ public class PhysicalPortUpdateCommand extends AbstractTransactCommand {
                         getOperationalState(), vlanBinding);
 
                 if (!HwvtepSouthboundUtil.isEmptyMap(configDependencies)) {
-                    createConfigWaitJob(psNodeiid, tp,
-                            vlanBinding, configDependencies, vlanIid);
+                    createConfigWaitJob(psNodeiid, inputPhysicalPort, key, configDependencies);
                     continue;
                 }
                 if (!HwvtepSouthboundUtil.isEmptyMap(inTransitDependencies)) {
-                    createOperWaitingJob(psNodeiid, tp,
-                            vlanBinding, inTransitDependencies, vlanIid);
+                    createOperWaitingJob(psNodeiid, inputPhysicalPort, key, inTransitDependencies);
                     continue;
                 }
 
@@ -147,61 +208,65 @@ public class PhysicalPortUpdateCommand extends AbstractTransactCommand {
                 }
                 bindingMap.put(vlanBinding.getVlanIdKey().getValue().longValue(), lsUUid);
             }
-            physicalPort.setVlanBindings(bindingMap);
         }
+        physicalPort.setVlanBindings(bindingMap);
+        return bindingMap;
     }
 
     private void createOperWaitingJob(final InstanceIdentifier<Node> psNodeiid,
                                       final TerminationPoint inputPhysicalPort,
-                                      final VlanBindings vlanBinding,
-                                      final Map inTransitDependencies,
-                                      final InstanceIdentifier<VlanBindings> vlanIid) {
-
-        DependentJob<VlanBindings> opWaitingJob = new DependentJob.OpWaitingJob<VlanBindings>(
-                vlanIid, vlanBinding, inTransitDependencies, getOperationalState().getTransactionId()) {
+                                      final InstanceIdentifier<TerminationPoint> key,
+                                      final Map inTransitDependencies) {
+        if (getDeviceInfo().isKeyInDependencyQueue(key)) {
+            return;
+        }
+        DependentJob<VlanBindings> opWaitingJob = new DependentJob.OpWaitingJob(
+                key, inputPhysicalPort, inTransitDependencies, getOperationalState().getTransactionId()) {
             @Override
             public void onDependencyResolved(final HwvtepOperationalState operationalState,
                                              final TransactionBuilder transactionBuilder) {
-                hwvtepOperationalState = operationalState;
-                deviceTransaction = transactionBuilder;
-                updatePhysicalPort(transactionBuilder, psNodeiid, Lists.newArrayList(inputPhysicalPort));
+                LOG.info("physical port oper dependency resolved {}", key);//TODO delete
+                PhysicalPortUpdateCommand.this.hwvtepOperationalState = operationalState;
+                HwvtepDeviceInfo.DeviceData deviceData = getOperationalState().getDeviceInfo().getConfigData(
+                        VlanBindings.class, key);
+                TerminationPoint port = inputPhysicalPort;
+                if (deviceData != null && deviceData.getData() != null) {
+                    port = (TerminationPoint) deviceData.getData();
+                }
+                doDeviceTransaction(transactionBuilder, psNodeiid, port, key);
             }
         };
+        LOG.info("Added the port to oper wait queue {}", key);//TODO delete
         getDeviceInfo().addJobToQueue(opWaitingJob);
     }
 
     private void createConfigWaitJob(final InstanceIdentifier<Node> psNodeiid,
                                      final TerminationPoint inputPhysicalPort,
-                                     final VlanBindings vlanBinding,
-                                     final Map configDependencies,
-                                     final InstanceIdentifier<VlanBindings> vlanIid) {
-
-        DependentJob<VlanBindings> configWaitingJob = new DependentJob.ConfigWaitingJob<VlanBindings>(
-                vlanIid, vlanBinding, configDependencies) {
+                                     final InstanceIdentifier<TerminationPoint> key,
+                                     final Map configDependencies) {
+        if (getDeviceInfo().isKeyInDependencyQueue(key)) {
+            return;
+        }
+        DependentJob<TerminationPoint> configWaitingJob = new DependentJob.ConfigWaitingJob(
+                key, inputPhysicalPort, configDependencies) {
             @Override
             public void onDependencyResolved(final HwvtepOperationalState operationalState,
                                              final TransactionBuilder transactionBuilder) {
-                hwvtepOperationalState = operationalState;
-                deviceTransaction = transactionBuilder;
-                updatePhysicalPort(transactionBuilder, psNodeiid, Lists.newArrayList(inputPhysicalPort));
+                LOG.info("physical port config dependency resolved {}", key);//TODO delete
+                PhysicalPortUpdateCommand.this.hwvtepOperationalState = operationalState;
+                HwvtepDeviceInfo.DeviceData deviceData = getOperationalState().getDeviceInfo().getConfigData(
+                        VlanBindings.class, key);
+                TerminationPoint port = inputPhysicalPort;
+                if (deviceData != null && deviceData.getData() != null) {
+                    port = (TerminationPoint) deviceData.getData();
+                }
+                doDeviceTransaction(transactionBuilder, psNodeiid, port, key);
             }
         };
+        LOG.info("Added the port to config wait queue {}", key);//TODO delete
         getDeviceInfo().addJobToQueue(configWaitingJob);
     }
 
-    private static InstanceIdentifier<TerminationPoint> getTpIid(final InstanceIdentifier<Node> psNodeiid,
-                                                                 final String portName) {
-        return psNodeiid.child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
-    }
-
-    private static InstanceIdentifier<VlanBindings> getVlanBindingIid(final InstanceIdentifier<Node> psNodeiid,
-                                                                      final PhysicalPort physicalPort,
-                                                                      final VlanBindings vlanBinding) {
-        return getTpIid(psNodeiid, physicalPort.getName())
-                .augmentation(HwvtepPhysicalPortAugmentation.class)
-                .child(VlanBindings.class, new VlanBindingsKey(vlanBinding.getVlanIdKey()));
-    }
-
     static class VlanBindingsUnMetDependencyGetter extends UnMetDependencyGetter<VlanBindings> {
 
         @Override
index 7007b1e432dd6ed60bc69c84c1ab368fa3c2f2c0..5f7104654eb6fbb42dafbdc8c786b096333de2a2 100644 (file)
@@ -9,16 +9,22 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
+import com.google.common.collect.Lists;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
+
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
 import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
+import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+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.RemoteUcastMacs;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -39,62 +45,104 @@ public class UcastMacsRemoteRemoveCommand extends AbstractTransactCommand<Remote
                 extractRemoved(getChanges(),RemoteUcastMacs.class);
         if (!removeds.isEmpty()) {
             for (Entry<InstanceIdentifier<Node>, List<RemoteUcastMacs>> removed:
-                removeds.entrySet()) {
-                removeUcastMacRemote(transaction,  removed.getKey(), removed.getValue());
+                    removeds.entrySet()) {
+                onConfigUpdate(transaction, removed.getKey(), removed.getValue());
             }
         }
     }
 
+    public void onConfigUpdate(TransactionBuilder transaction,
+                               InstanceIdentifier<Node> nodeIid,
+                               List<RemoteUcastMacs> macs) {
+        for (RemoteUcastMacs mac : macs) {
+            InstanceIdentifier<RemoteUcastMacs> macKey = nodeIid.augmentation(HwvtepGlobalAugmentation.class)
+                    .child(RemoteUcastMacs.class, mac.key());
+            getDeviceInfo().clearConfigData(RemoteUcastMacs.class, macKey);
+            onConfigUpdate(transaction, nodeIid, mac, macKey);
+        }
+    }
+
+    @Override
+    public void onConfigUpdate(TransactionBuilder transaction,
+                               InstanceIdentifier<Node> nodeIid,
+                               RemoteUcastMacs remoteMcastMac,
+                               InstanceIdentifier macKey,
+                               Object... extraData) {
+        processDependencies(EmptyDependencyGetter.INSTANCE, transaction, nodeIid, macKey, remoteMcastMac);
+    }
+
+    @Override
+    public void doDeviceTransaction(TransactionBuilder transaction,
+                                    InstanceIdentifier<Node> instanceIdentifier,
+                                    RemoteUcastMacs mac,
+                                    InstanceIdentifier macKey,
+                                    Object... extraData) {
+        removeUcastMacRemote(transaction, instanceIdentifier, Lists.newArrayList(mac));
+    }
 
     private void removeUcastMacRemote(final TransactionBuilder transaction,
                                       final InstanceIdentifier<Node> instanceIdentifier,
                                       final List<RemoteUcastMacs> macList) {
         for (RemoteUcastMacs mac: macList) {
-            onConfigUpdate(transaction, instanceIdentifier, mac, null);
+            final InstanceIdentifier<RemoteUcastMacs> macIid =
+                    instanceIdentifier.augmentation(HwvtepGlobalAugmentation.class)
+                            .child(RemoteUcastMacs.class, mac.key());
+            HwvtepDeviceInfo.DeviceData deviceData = getDeviceOpData(RemoteUcastMacs.class, macIid);
+            UcastMacsRemote ucastMacsRemote = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
+                    UcastMacsRemote.class, null);
+            LOG.debug("Remove received for remoteUcastMacs, key: {} txId: {}", macIid,
+                    getOperationalState().getTransactionId());
+            boolean deleted = false;
+            if (deviceData != null && deviceData.getUuid() != null) {
+                if (deviceData.getData() != null && deviceData.getData() instanceof UcastMacsRemote
+                        && ((UcastMacsRemote)deviceData.getData()).getLogicalSwitchColumn() != null) {
+                    UUID logicalSwitchUid = ((UcastMacsRemote) deviceData.getData()).getLogicalSwitchColumn().getData();
+                    if (logicalSwitchUid != null) {
+                        deleted = true;
+                        updateCurrentTxDeleteData(RemoteUcastMacs.class, macIid, mac);
+                        transaction.add(op.delete(ucastMacsRemote.getSchema())
+                                .where(ucastMacsRemote.getLogicalSwitchColumn().getSchema()
+                                        .opEqual(logicalSwitchUid))
+                                .and(ucastMacsRemote.getMacColumn().getSchema().opEqual(mac.getMacEntryKey()
+                                        .getValue())).build());
+                        LOG.info("CONTROLLER - {} {}", TransactionType.DELETE, ucastMacsRemote);
+                    }
+                }
+            }
+            if (!deleted && deviceData != null && deviceData.getUuid() != null) {
+                updateCurrentTxDeleteData(RemoteUcastMacs.class, macIid, mac);
+                UUID macEntryUUID = deviceData.getUuid();
+                ucastMacsRemote.getUuidColumn().setData(macEntryUUID);
+                transaction.add(op.delete(ucastMacsRemote.getSchema())
+                        .where(ucastMacsRemote.getUuidColumn().getSchema().opEqual(macEntryUUID)).build());
+                LOG.info("CONTROLLER - {} {}", TransactionType.DELETE, ucastMacsRemote);
+            } else {
+                LOG.trace("Remove failed to find in op datastore key:{} txId:{}", macIid, getOperationalState()
+                        .getTransactionId());
+            }
+            getDeviceInfo().clearConfigData(RemoteUcastMacs.class, macIid);
         }
     }
 
     @Override
-    public void onConfigUpdate(final TransactionBuilder transaction,
-                               final InstanceIdentifier<Node> nodeIid,
-                               final RemoteUcastMacs remoteUcastMacs,
-                               final InstanceIdentifier macKey,
-                               final Object... extraData) {
-        InstanceIdentifier<RemoteUcastMacs> macIid = nodeIid.augmentation(HwvtepGlobalAugmentation.class)
-                .child(RemoteUcastMacs.class, remoteUcastMacs.key());
-        processDependencies(null, transaction, nodeIid, macIid, remoteUcastMacs);
+    protected List<RemoteUcastMacs> getData(final HwvtepGlobalAugmentation augmentation) {
+        return augmentation.getRemoteUcastMacs();
     }
 
     @Override
-    public void doDeviceTransaction(final TransactionBuilder transaction,
-                                    final InstanceIdentifier<Node> instanceIdentifier,
-                                    final RemoteUcastMacs mac,
-                                    final InstanceIdentifier macKey,
-                                    final Object... extraData) {
-        LOG.debug("Removing remoteUcastMacs, mac address: {}", mac.getMacEntryKey().getValue());
-        InstanceIdentifier<RemoteUcastMacs> macIid = instanceIdentifier.augmentation(HwvtepGlobalAugmentation.class)
-                .child(RemoteUcastMacs.class, mac.key());
-        HwvtepDeviceInfo.DeviceData deviceData =
-                getOperationalState().getDeviceInfo().getDeviceOperData(RemoteUcastMacs.class, macIid);
-        UcastMacsRemote ucastMacsRemote = transaction.getTypedRowSchema(UcastMacsRemote.class);
-        if (deviceData != null && deviceData.getUuid() != null) {
-            //when mac entry is deleted, its referenced locators are deleted automatically.
-            //locators in config DS is not deleted and need to be removed explicitly by user.
-            UUID macEntryUUID = deviceData.getUuid();
-            ucastMacsRemote.getUuidColumn().setData(macEntryUUID);
-            transaction.add(op.delete(ucastMacsRemote.getSchema())
-                    .where(ucastMacsRemote.getUuidColumn().getSchema().opEqual(macEntryUUID)).build());
-            transaction.add(op.comment("UcastMacRemote: Deleting " + mac.getMacEntryKey().getValue()));
-            updateCurrentTxDeleteData(RemoteUcastMacs.class, macKey, mac);
-        } else {
-            LOG.warn("Unable to delete remoteUcastMacs {} because it was not found in the operational store",
-                    mac.getMacEntryKey().getValue());
-        }
+    protected boolean areEqual(RemoteUcastMacs remoteUcastMacs1, RemoteUcastMacs remoteUcastMacs2) {
+        return Objects.equals(remoteUcastMacs1.key(), remoteUcastMacs2.key());
     }
 
     @Override
-    protected List<RemoteUcastMacs> getData(final HwvtepGlobalAugmentation augmentation) {
-        return augmentation.getRemoteUcastMacs();
+    public void onSuccess(TransactionBuilder tx) {
+        for (MdsalUpdate mdsalUpdate : updates) {
+            RemoteUcastMacs mac = (RemoteUcastMacs) mdsalUpdate.getNewData();
+            InstanceIdentifier<RemoteUcastMacs> macIid = mdsalUpdate.getKey();
+            getDeviceInfo().removeRemoteUcast(
+                    (InstanceIdentifier<LogicalSwitches>) mac.getLogicalSwitchRef().getValue(), macIid);
+        }
+        getDeviceInfo().onOperDataAvailable();
     }
 
     @Override
index 3769806ccd339dda536a0a1bf9ed55a792a9cecd..451805aacfa89107ee76eb8f96598b57cc3a1504 100644 (file)
@@ -9,16 +9,21 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
+import com.google.common.collect.Lists;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
+
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
 import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
+import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
 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.RemoteUcastMacs;
@@ -56,6 +61,10 @@ public class UcastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
             return;
         }
         for (RemoteUcastMacs remoteUcastMac : remoteUcastMacs) {
+            InstanceIdentifier<RemoteUcastMacs> macIid =
+                    instanceIdentifier.augmentation(HwvtepGlobalAugmentation.class)
+                            .child(RemoteUcastMacs.class, remoteUcastMac.key());
+            getDeviceInfo().updateConfigData(RemoteUcastMacs.class, macIid, remoteUcastMac);
             onConfigUpdate(transaction, instanceIdentifier, remoteUcastMac, null);
         }
     }
@@ -77,33 +86,50 @@ public class UcastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
                                     final RemoteUcastMacs remoteUcastMac,
                                     final InstanceIdentifier macKey,
                                     final Object... extraData) {
-        LOG.debug("Creating remoteUcastMacs, mac address: {}", remoteUcastMac.getMacEntryKey().getValue());
+        LOG.debug("DoDeviceTransaction remoteUcastMacs, mac address: {}", remoteUcastMac.getMacEntryKey().getValue());
         updateConfigData(RemoteUcastMacs.class, macKey, remoteUcastMac);
-        final HwvtepDeviceInfo.DeviceData deviceData =
-                getOperationalState().getDeviceInfo().getDeviceOperData(RemoteUcastMacs.class, macKey);
-
+        HwvtepDeviceInfo.DeviceData deviceData = getDeviceOpData(RemoteUcastMacs.class, macKey);
         UcastMacsRemote ucastMacsRemote = transaction.getTypedRowWrapper(UcastMacsRemote.class);
         setIpAddress(ucastMacsRemote, remoteUcastMac);
-        setLocator(transaction, ucastMacsRemote, remoteUcastMac);
         setLogicalSwitch(transaction, ucastMacsRemote, remoteUcastMac);
-        if (deviceData == null) {
+        //TODO handle multiple inserts
+        if (deviceData  == null) {
+            setLocator(transaction, ucastMacsRemote, remoteUcastMac);
             setMac(ucastMacsRemote, remoteUcastMac);
-            LOG.trace("doDeviceTransaction: creating RemotUcastMac entry: {}", ucastMacsRemote);
+            LOG.trace("DoDeviceTransaction: creating RemotUcastMac entry: {} txId: {}", macKey,
+                    getOperationalState().getTransactionId());
             transaction.add(op.insert(ucastMacsRemote));
-            getOperationalState().getDeviceInfo().markKeyAsInTransit(RemoteUcastMacs.class, macKey);
             updateCurrentTxData(RemoteUcastMacs.class, macKey, new UUID("uuid"), remoteUcastMac);
+            LOG.info("CONTROLLER - {} {}", TransactionType.ADD, ucastMacsRemote);
+            return;
         } else if (deviceData.getUuid() != null) {
+            UUID newLocator = setLocator(transaction, ucastMacsRemote, remoteUcastMac);
+            if (deviceData.getData() != null) {
+                UcastMacsRemote existing = (UcastMacsRemote) deviceData.getData();
+                if (existing.getLocatorColumn() != null) {
+                    UUID oldLocatorUuid = existing.getLocatorColumn().getData();
+                    if (Objects.equals(newLocator, oldLocatorUuid)) {
+                        return;
+                    }
+                }
+            }
+            setMac(ucastMacsRemote, remoteUcastMac);
             UUID macEntryUUID = deviceData.getUuid();
-            UcastMacsRemote extraMac = transaction.getTypedRowSchema(UcastMacsRemote.class);
+            UcastMacsRemote extraMac = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
+                    UcastMacsRemote.class, null);
             extraMac.getUuidColumn().setData(macEntryUUID);
-            LOG.trace("doDeviceTransaction: updating RemotUcastMac entry: {}", ucastMacsRemote);
+            LOG.trace("doDeviceTransaction: updating RemotUcastMac entry: {} txId: {}", macKey,
+                    getOperationalState().getTransactionId());
             transaction.add(op.update(ucastMacsRemote)
                     .where(extraMac.getUuidColumn().getSchema().opEqual(macEntryUUID))
                     .build());
+            LOG.info("CONTROLLER - {} {}", TransactionType.UPDATE, ucastMacsRemote);
+            addToUpdates(macKey, remoteUcastMac);
         } else {
-            LOG.warn("Unable to update remoteMcastMacs {} because uuid not found in the operational store",
-                    remoteUcastMac.getMacEntryKey().getValue());
+            LOG.warn("Unable to update remoteUcastMacs {} because uuid not found in the operational store txId: {}",
+                    macKey, getOperationalState().getTransactionId());
         }
+        return;
     }
 
     private void setLogicalSwitch(final TransactionBuilder transaction, final UcastMacsRemote ucastMacsRemote,
@@ -112,23 +138,25 @@ public class UcastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
             @SuppressWarnings("unchecked")
             InstanceIdentifier<LogicalSwitches> lswitchIid =
                     (InstanceIdentifier<LogicalSwitches>) inputMac.getLogicalSwitchRef().getValue();
-            ucastMacsRemote.setLogicalSwitch(TransactUtils.getLogicalSwitchUUID(
-                    transaction, getOperationalState(), lswitchIid));
+            UUID logicalSwitchUUID = TransactUtils.getLogicalSwitchUUID(transaction, getOperationalState(), lswitchIid);
+            if (logicalSwitchUUID != null) {
+                ucastMacsRemote.setLogicalSwitch(TransactUtils.getLogicalSwitchUUID(transaction, getOperationalState(),
+                        lswitchIid));
+            }
         }
     }
 
-    private void setLocator(final TransactionBuilder transaction, final UcastMacsRemote ucastMacsRemote,
-            final RemoteUcastMacs inputMac) {
+    private UUID setLocator(TransactionBuilder transaction, UcastMacsRemote ucastMacsRemote, RemoteUcastMacs inputMac) {
         //get UUID by locatorRef
         if (inputMac.getLocatorRef() != null) {
             @SuppressWarnings("unchecked")
-            InstanceIdentifier<TerminationPoint> iid = (InstanceIdentifier<TerminationPoint>)
-                    inputMac.getLocatorRef().getValue();
+            InstanceIdentifier<TerminationPoint> iid =
+                    (InstanceIdentifier<TerminationPoint>) inputMac.getLocatorRef().getValue();
             UUID locatorUuid = TransactUtils.createPhysicalLocator(transaction, getOperationalState(), iid);
-            if (locatorUuid != null) {
-                ucastMacsRemote.setLocator(locatorUuid);
-            }
+            ucastMacsRemote.setLocator(locatorUuid);
+            return locatorUuid;
         }
+        return null;
     }
 
     private static void setIpAddress(final UcastMacsRemote ucastMacsRemote, final RemoteUcastMacs inputMac) {
@@ -153,20 +181,26 @@ public class UcastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
         @Override
         public List<InstanceIdentifier<?>> getLogicalSwitchDependencies(final RemoteUcastMacs data) {
             if (data == null) {
-                return Collections.emptyList();
+                return Collections.EMPTY_LIST;
             }
-            return Collections.singletonList(data.getLogicalSwitchRef().getValue());
+            return Lists.newArrayList(data.getLogicalSwitchRef().getValue());
         }
 
         @Override
         public List<InstanceIdentifier<?>> getTerminationPointDependencies(final RemoteUcastMacs data) {
             if (data == null) {
-                return Collections.emptyList();
+                return Collections.EMPTY_LIST;
             }
-            return Collections.singletonList(data.getLocatorRef().getValue());
+            return Lists.newArrayList(data.getLocatorRef().getValue());
         }
     }
 
+    @Override
+    protected boolean areEqual(RemoteUcastMacs remoteUcastMacs1, RemoteUcastMacs remoteUcastMacs2) {
+        return Objects.equals(remoteUcastMacs1.key(), remoteUcastMacs2.key())
+                && Objects.equals(remoteUcastMacs1.getLocatorRef(), remoteUcastMacs2.getLocatorRef());
+    }
+
     @Override
     public void onSuccess(TransactionBuilder tx) {
         for (MdsalUpdate mdsalUpdate : updates) {
index 5a3355c4f818872d003b9cc8ea2d10ba550fab7b..673348b8176448c901b6bcb348a053040857d822 100644 (file)
@@ -44,9 +44,11 @@ import org.opendaylight.ovsdb.lib.operations.Delete;
 import org.opendaylight.ovsdb.lib.operations.Insert;
 import org.opendaylight.ovsdb.lib.operations.OperationResult;
 import org.opendaylight.ovsdb.lib.operations.Operations;
+import org.opendaylight.ovsdb.lib.operations.Select;
 import org.opendaylight.ovsdb.lib.operations.Update;
 import org.opendaylight.ovsdb.lib.operations.Where;
 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
 import org.opendaylight.ovsdb.lib.schema.typed.TypedDatabaseSchema;
 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionHistory;
@@ -208,9 +210,13 @@ public class DataChangeListenerTestBase extends AbstractDataBrokerTest {
         doReturn(insert).when(mockOp).insert(insertOpCapture.capture());
         Update update = mock(Update.class);
         doReturn(update).when(mockOp).update(insertOpCapture.capture());
+        Select select = mock(Select.class);
+        doReturn(select).when(mockOp).select(any(GenericTableSchema.class));
         doReturn(where).when(update).where(any());
         doReturn(delete).when(mockOp).delete(any());
 
+
+
         try {
             setFinalStatic(Operations.class, "op", mockOp);
         } catch (SecurityException | ReflectiveOperationException e) {