bug 6579 removed boilerplate code 29/48929/13
authorK.V Suneelu Verma <k.v.suneelu.verma@ericsson.com>
Fri, 2 Dec 2016 14:54:50 +0000 (20:24 +0530)
committersuneel verma <k.v.suneelu.verma@ericsson.com>
Wed, 28 Dec 2016 03:06:49 +0000 (03:06 +0000)
removed the boilerplate code from commands moved it to super class
pulled the methods extractUpdated and extractRemoved to super class
child class implements getData and areEqual methods

extractUpdated method compares old data and new data and returns the
change set.
Comparison logic is taken care by the sub class.

extractDeleted gets the deleted keys .
for local ucast mac remove command ,If logical switch is deleted ,
it will return the local ucast macs to be deleted aswell.

logical switch removal is fired in seperate transaction to avoid
failure of transaction because of some local references which odl is not
aware of sometimes due to racing conditions.

if mcast mac locator set gets emptied , fire removal of mcast mac
if the json rpc transaction fails, clear the intransit data from device
info

Change-Id: Ia172b5887887f202ba1149ba748862d86f9c9869
Signed-off-by: K.V Suneelu Verma <k.v.suneelu.verma@ericsson.com>
28 files changed:
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepConnectionInstance.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDeviceInfo.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepSouthboundUtil.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/reconciliation/configuration/GlobalConfigOperationalChangeGetter.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/AbstractTransactCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/DependencyQueue.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/LogicalSwitchRemoveCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/LogicalSwitchUpdateCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/McastMacsLocalRemoveCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/McastMacsLocalUpdateCommand.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/PhysicalPortRemoveCommand.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/PhysicalSwitchRemoveCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/PhysicalSwitchUpdateCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/TransactInvokerImpl.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/TransactUtils.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/UcastMacsLocalRemoveCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transact/UcastMacsLocalUpdateCommand.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/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transactions/md/HwvtepPhysicalLocatorUpdateCommand.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/DataChangeListenerTestBase.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDataChangeListenerTest.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepOperationalDataChangeListener.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/TestBuilders.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/test/resources/org/opendaylight/ovsdb/hwvtepsouthbound/hwvtep_schema.json

index cec5fc852243b21da8ad2847d3f409ac92614d1e..1741042b7062b14d45d51657ba7ba3cf4533d70a 100644 (file)
@@ -80,7 +80,7 @@ public class HwvtepConnectionInstance {
         this.dataBroker = dataBroker;
     }
 
-    public void transact(TransactCommand command) {
+    public synchronized void transact(TransactCommand command) {
         for (TransactInvoker transactInvoker: transactInvokers.values()) {
             transactInvoker.invoke(command);
         }
index ba0b1a3886105dbc54c2f37f8e9be29d250812d4..0c8fec7f99069037afe8c7469390b1d109431b40 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.ovsdb.hwvtepsouthbound;
 
 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.lib.notation.UUID;
 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
@@ -22,6 +23,7 @@ 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;
 
@@ -177,16 +179,22 @@ public class HwvtepDeviceInfo {
                 new DeviceData(key, null, data, DeviceDataStatus.AVAILABLE));
     }
 
+    public Object getConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+        return HwvtepSouthboundUtil.getData(configKeyVsData, cls, key);
+    }
+
     public void clearConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
         HwvtepSouthboundUtil.clearData(configKeyVsData, cls, key);
     }
 
     public void markKeyAsInTransit(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+        LOG.debug("Marking device data as intransit {}", key);
         HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key,
                 new DeviceData(key, null, null, DeviceDataStatus.IN_TRANSIT));
     }
 
     public void updateDeviceOpData(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);
@@ -227,4 +235,27 @@ public class HwvtepDeviceInfo {
     public void onOpDataAvailable() {
         dependencyQueue.processReadyJobsFromOpQueue(connectionInstance);
     }
+
+    public void scheduleTransaction(final TransactCommand transactCommand) {
+        dependencyQueue.submit(new Runnable() {
+            @Override
+            public void run() {
+                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();
+                }
+            }
+        }
+        onOpDataAvailable();
+    }
 }
index eb29948f9647b041669a1f0311c05e7a7f9cfc1d..0a21cb73a0d62d81d2cd45d46274f55b439d8099 100644 (file)
@@ -21,15 +21,25 @@ 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.HwvtepGlobalRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalSwitchAttributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ConnectionInfo;
+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;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 
 public class HwvtepSouthboundUtil {
@@ -183,7 +193,11 @@ public class HwvtepSouthboundUtil {
         }
     }
 
-    public static <T> boolean isEmpty(List<T> list) {
+    public static <T> boolean isEmpty(Collection<T> list) {
         return list == null || list.isEmpty();
     }
+
+    public static boolean isEmptyMap(Map map) {
+        return map == null || map.isEmpty();
+    }
 }
index 599a6bff24aaddf082d229df6dec2c2c5add1fb5..20180ca7cf8cc4eee361a01245e03c29add834a8 100644 (file)
@@ -38,7 +38,7 @@ public class GlobalConfigOperationalChangeGetter {
         HwvtepGlobalAugmentationBuilder oldAugmentation = getAugmentationFromNode(opNode);
 
         //fire removal of local ucast macs so that logical switches will be deleted
-        fillLocalMcacsToBeRemoved(oldAugmentation, configNode, opNode);
+        fillLocalMacsToBeRemoved(oldAugmentation, configNode, opNode);
 
         newNodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, newAugmentation.build());
         oldNodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, oldAugmentation.build());
@@ -46,8 +46,7 @@ public class GlobalConfigOperationalChangeGetter {
         return new DataTreeModificationImpl<Node>(nodeId, newNodeBuilder.build(), oldNodeBuilder.build());
     }
 
-    static void fillLocalMcacsToBeRemoved(HwvtepGlobalAugmentationBuilder oldAugmentation, Node configNode,
-                                          Node opNode) {
+    static void fillLocalMacsToBeRemoved(HwvtepGlobalAugmentationBuilder oldAugmentation, Node configNode, Node opNode) {
         Set<String> logicalSwitchNamesToBeRemoved = getLogicalSwitchesToBeRemoved(configNode, opNode);
         List<LocalUcastMacs> localUcastMacsToBeRemoved = getLocalUcastMacsToBeRemoved(opNode,
                 logicalSwitchNamesToBeRemoved);
@@ -110,9 +109,12 @@ public class GlobalConfigOperationalChangeGetter {
         Set<String> opSwitchNames = new HashSet<>();
         Set<String> cfgSwitchNames = new HashSet<>();
         List<LogicalSwitches> cfgLogicalSwitches = Lists.newArrayList();
+        List<LogicalSwitches> opLogicalSwitches = Lists.newArrayList();
 
-        List<LogicalSwitches> opLogicalSwitches = opNode.getAugmentation(HwvtepGlobalAugmentation.class).getLogicalSwitches();
-        if (configNode != null) {
+        if (opNode != null && opNode.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
+            opLogicalSwitches = opNode.getAugmentation(HwvtepGlobalAugmentation.class).getLogicalSwitches();
+        }
+        if (configNode != null && configNode.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
             cfgLogicalSwitches = configNode.getAugmentation(HwvtepGlobalAugmentation.class).getLogicalSwitches();
         }
         if (opLogicalSwitches != null) {
index c62dc862ff7fc5ff79a1036d676a06d4a7c2ca37..349cf3db26cfa17732783a6f1e7ce8e62532dbfd 100644 (file)
@@ -8,20 +8,38 @@
 
 package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
 
 import com.google.common.collect.Lists;
+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.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.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+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.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.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-public abstract class AbstractTransactCommand<T extends Identifiable> implements TransactCommand<T> {
+public abstract class AbstractTransactCommand<T extends Identifiable, Aug extends Augmentation<Node>> implements TransactCommand<T> {
 
     private HwvtepOperationalState operationalState;
     private Collection<DataTreeModification<Node>> changes;
@@ -43,8 +61,7 @@ public abstract class AbstractTransactCommand<T extends Identifiable> implements
         return changes;
     }
 
-    void updateCurrentTxDeleteData(InstanceIdentifier key, T data) {
-        Class<? extends Identifiable> cls = data.getClass();
+    void updateCurrentTxDeleteData(Class<? extends Identifiable> cls, InstanceIdentifier key, T data) {
         operationalState.updateCurrentTxDeleteData(cls, key);
         operationalState.getDeviceInfo().clearConfigData(cls, key);
     }
@@ -67,17 +84,20 @@ public abstract class AbstractTransactCommand<T extends Identifiable> implements
         //we can skip the config termination point dependency as we can create them in device as part of this tx
         confingDependencies.remove(TerminationPoint.class);
 
+        Type type = getClass().getGenericSuperclass();
+        Type classType = ((ParameterizedType)type).getActualTypeArguments()[0];
+
         //If this key itself is in transit wait for the response of this key itself
-        if (deviceInfo.isKeyInTransit(data.getClass(), key)) {
-            inTransitDependencies.put(data.getClass(), Lists.newArrayList(key));
+        if (deviceInfo.isKeyInTransit((Class<? extends Identifiable>) classType, key)) {
+            inTransitDependencies.put((Class<? extends Identifiable>) classType, Lists.newArrayList(key));
         }
 
-        if (confingDependencies.isEmpty() && inTransitDependencies.isEmpty()) {
+        if (HwvtepSouthboundUtil.isEmptyMap(confingDependencies) && HwvtepSouthboundUtil.isEmptyMap(inTransitDependencies)) {
             doDeviceTransaction(transaction, nodeIid, data, key, extraData);
             //TODO put proper uuid
-            updateCurrentTxData(data.getClass(), key, new UUID("uuid"), data);
+            updateCurrentTxData((Class<? extends Identifiable>) classType, key, new UUID("uuid"), data);
         }
-        if (!confingDependencies.isEmpty()) {
+        if (!HwvtepSouthboundUtil.isEmptyMap(confingDependencies)) {
             DependentJob<T> configWaitingJob = new DependentJob.ConfigWaitingJob(
                     key, data, confingDependencies) {
 
@@ -90,7 +110,7 @@ public abstract class AbstractTransactCommand<T extends Identifiable> implements
             };
             deviceInfo.addJobToQueue(configWaitingJob);
         }
-        if (inTransitDependencies.size() > 0) {
+        if (!HwvtepSouthboundUtil.isEmptyMap(inTransitDependencies)) {
 
             DependentJob<T> opWaitingJob = new DependentJob.OpWaitingJob(
                     key, data, inTransitDependencies) {
@@ -115,4 +135,158 @@ public abstract class AbstractTransactCommand<T extends Identifiable> implements
                                InstanceIdentifier key, Object... extraData) {
         //tobe removed as part of refactoring patch
     }
+
+    protected Aug getAugmentation(Node node) {
+        if (node == null) {
+            return null;
+        }
+        ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
+        Class<? extends Augmentation<Node>> augType = (Class<? extends Augmentation<Node>>) parameterizedType.getActualTypeArguments()[1];
+        Augmentation<Node> augmentation = node.getAugmentation(augType);
+        return (Aug)augmentation;
+    }
+
+    protected List<T> getData(Aug augmentation) {
+        return Collections.EMPTY_LIST;
+    }
+
+    protected List<T> getData(Node node) {
+        Aug augmentation = getAugmentation(node);
+        if (augmentation != null) {
+            List<T> data = getData(augmentation);
+            if (data != null) {
+                return Lists.newArrayList(data);
+            }
+        }
+        return Collections.EMPTY_LIST;
+    }
+
+    protected Map<InstanceIdentifier<Node>, List<T>> extractRemoved(
+            Collection<DataTreeModification<Node>> changes, Class<T> class1) {
+        Map<InstanceIdentifier<Node>, List<T>> result
+                = new HashMap<InstanceIdentifier<Node>, List<T>>();
+        List<T> removed = Collections.EMPTY_LIST;
+        if (changes != null && !changes.isEmpty()) {
+            for (DataTreeModification<Node> change : changes) {
+                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+                removed = getRemoved(change);
+                removed.addAll(getCascadeDeleteData(change));
+                result.put(key, removed);
+            }
+        }
+        return result;
+    }
+
+    protected Map<InstanceIdentifier<Node>, List<T>> extractUpdated(
+            Collection<DataTreeModification<Node>> changes, Class<T> class1) {
+        Map<InstanceIdentifier<Node>, List<T>> result
+                = new HashMap<InstanceIdentifier<Node>, List<T>>();
+        if (changes != null && !changes.isEmpty()) {
+            for (DataTreeModification<Node> change : changes) {
+                InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+                result.put(key, getUpdated(change));
+            }
+        }
+        return result;
+    }
+
+    List<T>  getCascadeDeleteData(DataTreeModification<Node> change) {
+        if (!cascadeDelete()) {
+            return Collections.EMPTY_LIST;
+        }
+        DataObjectModification<Node> mod = change.getRootNode();
+        Node updatedNode = TransactUtils.getUpdated(mod);
+        List<T> updatedData = getData(updatedNode);
+        Set<InstanceIdentifier> deleted = getOperationalState().getDeletedKeysInCurrentTx(LogicalSwitches.class);
+        UnMetDependencyGetter dependencyGetter = getDependencyGetter();
+        if (!HwvtepSouthboundUtil.isEmpty(deleted) && !HwvtepSouthboundUtil.isEmpty(updatedData) && dependencyGetter != null) {
+            List<T> removed = new ArrayList<T>();
+            for (T ele : updatedData) {
+                if (deleted.containsAll(dependencyGetter.getLogicalSwitchDependencies(ele))) {
+                    removed.add(ele);
+                }
+            }
+            return removed;
+        }
+        return Collections.EMPTY_LIST;
+    }
+
+    List<T> getRemoved(DataTreeModification<Node> change) {
+        DataObjectModification<Node> mod = change.getRootNode();
+
+        Node removed = TransactUtils.getRemoved(mod);
+        Node updated = TransactUtils.getUpdated(mod);
+        Node before = mod.getDataBefore();
+        return diffOf(removed, before, updated, true);
+    }
+
+    List<T> getUpdated(DataTreeModification<Node> change) {
+        DataObjectModification<Node> mod = change.getRootNode();
+        Node created = TransactUtils.getCreated(mod);
+        Node updated = TransactUtils.getUpdated(mod);
+        Node before = mod.getDataBefore();
+        return diffOf(created, updated, before, false);
+    }
+
+    List<T> diffOf(Node include, Node a, Node b, boolean compareKeyOnly) {
+        List<T> data1 = getData(include);
+        List<T> data2 = diffOf(a, b, compareKeyOnly);
+        if (HwvtepSouthboundUtil.isEmpty(data1) && HwvtepSouthboundUtil.isEmpty(data2)) {
+            return Collections.EMPTY_LIST;
+        }
+        List<T> result = Lists.newArrayList(data1);
+        result.addAll(data2);
+        return result;
+    }
+
+    List<T> diffOf(Node a, Node b, boolean compareKeyOnly) {
+        List<T> result = new ArrayList<T>();
+
+        List<T> list1 = getData(a);
+        List<T> list2 = getData(b);
+
+        if (HwvtepSouthboundUtil.isEmpty(list1)) {
+            return Collections.EMPTY_LIST;
+        }
+        if (HwvtepSouthboundUtil.isEmpty(list2)) {
+            return HwvtepSouthboundUtil.isEmpty(list1) ? Collections.EMPTY_LIST : list1;
+        }
+
+        Iterator<T> it1 = list1.iterator();
+
+        while(it1.hasNext()) {
+            T ele = it1.next();
+            Iterator<T> it2 = list2.iterator();
+            boolean found = false;
+            while (it2.hasNext()) {
+                T other  = it2.next();
+                found = compareKeyOnly ? Objects.equals(ele.getKey(), other.getKey()) : areEqual(ele, other);
+                if ( found ) {
+                    it2.remove();
+                    break;
+                }
+            }
+            if (!found) {
+                result.add(ele);
+            }
+        }
+        return result;
+    }
+
+    protected boolean areEqual(T a , T b) {
+        return a.getKey().equals(b.getKey());
+    }
+
+    protected UnMetDependencyGetter getDependencyGetter() {
+        return null;
+    }
+
+    /**
+     * Tells if this object needs to be deleted if its dependent object gets deleted
+     * Ex : LocalUcastMac and LocalMacstMac
+     * @return true if this object needs to be deleted if its dependent object gets deleted
+     */
+    protected boolean cascadeDelete() {
+        return false;
+    }
 }
index 0b1b2eff77a77e15c85a0b11224327cfccfe6be1..c6892649da15fab0e4c30053ff3a3680b23696bf 100644 (file)
@@ -131,4 +131,8 @@ public class DependencyQueue {
     public static void close() {
         executorService.shutdown();
     }
+
+    public void submit(Runnable runnable) {
+        executorService.submit(runnable);
+    }
 }
\ No newline at end of file
index 6c84cc794a4934fd0aaacbaf4ad71c591b3cf710..0dadf6792b23253cc68b6ca9ab5b0693276dbf3f 100644 (file)
@@ -10,15 +10,14 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
-import java.util.ArrayList;
 import java.util.Collection;
-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.HwvtepSouthboundUtil;
 import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
@@ -26,13 +25,14 @@ import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
 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.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
-public class LogicalSwitchRemoveCommand extends AbstractTransactCommand {
+public class LogicalSwitchRemoveCommand extends AbstractTransactCommand<LogicalSwitches, HwvtepGlobalAugmentation> {
     private static final Logger LOG = LoggerFactory.getLogger(LogicalSwitchRemoveCommand.class);
 
     public LogicalSwitchRemoveCommand(HwvtepOperationalState state,
@@ -44,17 +44,32 @@ public class LogicalSwitchRemoveCommand extends AbstractTransactCommand {
     public void execute(TransactionBuilder transaction) {
         Map<InstanceIdentifier<Node>, List<LogicalSwitches>> removeds =
                 extractRemoved(getChanges(),LogicalSwitches.class);
-        if (!removeds.isEmpty()) {
-            for (Entry<InstanceIdentifier<Node>, List<LogicalSwitches>> created:
-                removeds.entrySet()) {
-                if (created.getValue() != null) {
+        if (removeds != null) {
+            for (Entry<InstanceIdentifier<Node>, List<LogicalSwitches>> created: removeds.entrySet()) {
+                if (!HwvtepSouthboundUtil.isEmpty(created.getValue())) {
                     for (LogicalSwitches lswitch : created.getValue()) {
                         InstanceIdentifier<LogicalSwitches> lsKey = created.getKey().augmentation(
                                 HwvtepGlobalAugmentation.class).child(LogicalSwitches.class, lswitch.getKey());
-                        updateCurrentTxDeleteData(lsKey, lswitch);
+                        updateCurrentTxDeleteData(LogicalSwitches.class, lsKey, lswitch);
                     }
+                    getOperationalState().getDeviceInfo().scheduleTransaction(new TransactCommand() {
+                        @Override
+                        public void execute(TransactionBuilder transactionBuilder) {
+                            LOG.debug("Running delete logical switch in seperate tx {}", created.getKey());
+                            removeLogicalSwitch(transactionBuilder, created.getKey(), created.getValue());
+                        }
+
+                        @Override
+                        public void onConfigUpdate(TransactionBuilder transaction, InstanceIdentifier nodeIid,
+                                                   Identifiable data, InstanceIdentifier key, Object... extraData) {
+                        }
+
+                        @Override
+                        public void doDeviceTransaction(TransactionBuilder transaction, InstanceIdentifier nodeIid,
+                                                        Identifiable data, InstanceIdentifier key, Object... extraData) {
+                        }
+                    });
                 }
-                removeLogicalSwitch(transaction,  created.getKey(), created.getValue());
             }
         }
     }
@@ -80,68 +95,13 @@ public class LogicalSwitchRemoveCommand extends AbstractTransactCommand {
         }
     }
 
-    private Map<InstanceIdentifier<Node>, List<LogicalSwitches>> extractRemoved(
-            Collection<DataTreeModification<Node>> changes, Class<LogicalSwitches> class1) {
-        Map<InstanceIdentifier<Node>, List<LogicalSwitches>> result
-            = new HashMap<InstanceIdentifier<Node>, List<LogicalSwitches>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                //If the node which logical switches belong to is removed, all logical switches
-                //should be removed too.
-                Node removed = TransactUtils.getRemoved(mod);
-                if (removed != null) {
-                    List<LogicalSwitches> lswitchListRemoved = null;
-                    if (removed.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
-                        lswitchListRemoved = removed.getAugmentation(HwvtepGlobalAugmentation.class).getLogicalSwitches();
-                    }
-                    if (lswitchListRemoved != null) {
-                        result.put(key, lswitchListRemoved);
-                    }
-                }
-                //If the node which logical switches belong to is updated, and logical switches may
-                //be created or updated or deleted, we need to get deleted ones.
-                Node updated = TransactUtils.getUpdated(mod);
-                Node before = mod.getDataBefore();
-                if (updated != null && before != null) {
-                    List<LogicalSwitches> lswitchListUpdated = null;
-                    List<LogicalSwitches> lswitchListBefore = null;
-                    if (updated.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
-                        lswitchListUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class).getLogicalSwitches();
-                    }
-                    if (before.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
-                        lswitchListBefore = before.getAugmentation(HwvtepGlobalAugmentation.class).getLogicalSwitches();
-                    }
-                    if (lswitchListBefore != null) {
-                        List<LogicalSwitches> lswitchListRemoved = new ArrayList<LogicalSwitches>();
-                        if (lswitchListUpdated != null) {
-                            lswitchListBefore = new ArrayList<>(lswitchListBefore);
-                            lswitchListBefore.removeAll(lswitchListUpdated);//operate on copy as it has side effect on LogicalSwitchUpdateCommand
-                        }
-                        //then exclude updated ones
-                        if (lswitchListUpdated != null) {
-                            for (LogicalSwitches lswitchBefore : lswitchListBefore) {
-                                int i = 0;
-                                for (; i < lswitchListUpdated.size(); i++) {
-                                    if (lswitchBefore.getHwvtepNodeName().equals(lswitchListUpdated.get(i).getHwvtepNodeName())) {
-                                        break;
-                                    }
-                                }
-                                if (i == lswitchListUpdated.size()) {
-                                    lswitchListRemoved.add(lswitchBefore);
-                                }
-                            }
-                        } else {
-                            lswitchListRemoved.addAll(lswitchListBefore);
-                        }
-                        if (!lswitchListRemoved.isEmpty()) {
-                            result.put(key, lswitchListRemoved);
-                        }
-                    }
-                }
-            }
-        }
-        return result;
+    @Override
+    protected List<LogicalSwitches> getData(HwvtepGlobalAugmentation augmentation) {
+        return augmentation.getLogicalSwitches();
+    }
+
+    @Override
+    protected boolean areEqual(LogicalSwitches a , LogicalSwitches b) {
+        return a.getKey().equals(b.getKey()) && Objects.equals(a.getTunnelKey(), b.getTunnelKey());
     }
 }
index a0068d40e21cfc390fcf564f5d4623a291e4cc61..693edb2c1b6866d9a1d0b9587590909a42dc95dd 100644 (file)
@@ -11,16 +11,14 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.HashSet;
 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.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-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;
@@ -34,7 +32,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
-public class LogicalSwitchUpdateCommand extends AbstractTransactCommand {
+public class LogicalSwitchUpdateCommand extends AbstractTransactCommand<LogicalSwitches, HwvtepGlobalAugmentation> {
     private static final Logger LOG = LoggerFactory.getLogger(LogicalSwitchUpdateCommand.class);
 
     public LogicalSwitchUpdateCommand(HwvtepOperationalState state,
@@ -44,14 +42,6 @@ public class LogicalSwitchUpdateCommand extends AbstractTransactCommand {
 
     @Override
     public void execute(TransactionBuilder transaction) {
-        Map<InstanceIdentifier<Node>, List<LogicalSwitches>> createds =
-                extractCreated(getChanges(),LogicalSwitches.class);
-        if (!createds.isEmpty()) {
-            for (Entry<InstanceIdentifier<Node>, List<LogicalSwitches>> created:
-                createds.entrySet()) {
-                updateLogicalSwitch(transaction,  created.getKey(), created.getValue());
-            }
-        }
         Map<InstanceIdentifier<Node>, List<LogicalSwitches>> updateds =
                 extractUpdated(getChanges(),LogicalSwitches.class);
         if (!updateds.isEmpty()) {
@@ -78,6 +68,8 @@ public class LogicalSwitchUpdateCommand extends AbstractTransactCommand {
                 LOG.trace("execute: creating LogicalSwitch entry: {}", logicalSwitch);
                 transaction.add(op.insert(logicalSwitch).withId(TransactUtils.getLogicalSwitchId(lswitch)));
                 transaction.add(op.comment("Logical Switch: Creating " + lswitch.getHwvtepNodeName().getValue()));
+                UUID lsUuid = new UUID(TransactUtils.getLogicalSwitchId(lswitch));
+                updateCurrentTxData(LogicalSwitches.class, lsKey, lsUuid, lswitch);
             } else {
                 LogicalSwitches updatedLSwitch = operationalSwitchOptional.get();
                 String existingLogicalSwitchName = updatedLSwitch.getHwvtepNodeName().getValue();
@@ -90,8 +82,6 @@ public class LogicalSwitchUpdateCommand extends AbstractTransactCommand {
                         .build());
                 transaction.add(op.comment("Logical Switch: Updating " + existingLogicalSwitchName));
             }
-            UUID lsUuid = new UUID(TransactUtils.getLogicalSwitchId(lswitch));
-            updateCurrentTxData(LogicalSwitches.class, lsKey, lsUuid, lswitch);
         }
     }
 
@@ -118,57 +108,13 @@ public class LogicalSwitchUpdateCommand extends AbstractTransactCommand {
         }
     }
 
-    private Map<InstanceIdentifier<Node>, List<LogicalSwitches>> extractCreated(
-            Collection<DataTreeModification<Node>> changes, Class<LogicalSwitches> class1) {
-        Map<InstanceIdentifier<Node>, List<LogicalSwitches>> result
-            = new HashMap<InstanceIdentifier<Node>, List<LogicalSwitches>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                Node created = TransactUtils.getCreated(mod);
-                if (created != null) {
-                    List<LogicalSwitches> lswitchListUpdated = null;
-                    if (created.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
-                        lswitchListUpdated = created.getAugmentation(HwvtepGlobalAugmentation.class).getLogicalSwitches();
-                    }
-                    if (lswitchListUpdated != null) {
-                        result.put(key, lswitchListUpdated);
-                    }
-                }
-            }
-        }
-        return result;
+    @Override
+    protected List<LogicalSwitches> getData(HwvtepGlobalAugmentation augmentation) {
+        return augmentation.getLogicalSwitches();
     }
 
-    private Map<InstanceIdentifier<Node>, List<LogicalSwitches>> extractUpdated(
-            Collection<DataTreeModification<Node>> changes, Class<LogicalSwitches> class1) {
-        Map<InstanceIdentifier<Node>, List<LogicalSwitches>> result
-            = new HashMap<InstanceIdentifier<Node>, List<LogicalSwitches>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                Node updated = TransactUtils.getUpdated(mod);
-                Node before = mod.getDataBefore();
-                if (updated != null && before != null) {
-                    List<LogicalSwitches> lswitchListUpdated = null;
-                    List<LogicalSwitches> lswitchListBefore = null;
-                    if (updated.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
-                        lswitchListUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class).getLogicalSwitches();
-                    }
-                    if (before.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
-                        lswitchListBefore = before.getAugmentation(HwvtepGlobalAugmentation.class).getLogicalSwitches();
-                    }
-                    if (lswitchListUpdated != null) {
-                        if (lswitchListBefore != null) {
-                            lswitchListUpdated.removeAll(lswitchListBefore);
-                        }
-                        result.put(key, lswitchListUpdated);
-                    }
-                }
-            }
-        }
-        return result;
+    @Override
+    protected boolean areEqual(LogicalSwitches a , LogicalSwitches b) {
+        return a.getKey().equals(b.getKey()) && Objects.equals(a.getTunnelKey(), b.getTunnelKey());
     }
 }
index e67b9d38fed89478b5575ff3f76ce3f59df1845b..1d6783dc0f9a91dde3ccc9f5810d773a60f4c2f0 100644 (file)
@@ -10,16 +10,14 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import com.google.common.collect.Lists;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
 import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
@@ -33,7 +31,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
-public class McastMacsLocalRemoveCommand extends AbstractTransactCommand {
+public class McastMacsLocalRemoveCommand extends AbstractTransactCommand<LocalMcastMacs, HwvtepGlobalAugmentation> {
     private static final Logger LOG = LoggerFactory.getLogger(McastMacsLocalRemoveCommand.class);
 
     public McastMacsLocalRemoveCommand(HwvtepOperationalState state,
@@ -76,68 +74,31 @@ public class McastMacsLocalRemoveCommand extends AbstractTransactCommand {
         }
     }
 
-    private Map<InstanceIdentifier<Node>, List<LocalMcastMacs>> extractRemoved(
-            Collection<DataTreeModification<Node>> changes, Class<LocalMcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<LocalMcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<LocalMcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                //If the node which localMcastMacs belong to is removed, all localMcastMacs should be removed too.
-                Node removed = TransactUtils.getRemoved(mod);
-                if (removed != null) {
-                    List<LocalMcastMacs> macListRemoved = null;
-                    if (removed.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
-                        macListRemoved = removed.getAugmentation(HwvtepGlobalAugmentation.class).getLocalMcastMacs();
-                    }
-                    if (macListRemoved != null) {
-                        result.put(key, macListRemoved);
-                    }
-                }
-                //If the node which localMcastMacs belong to is updated, and localMcastMacs may
-                //be created or updated or deleted, we need to get deleted ones.
-                Node updated = TransactUtils.getUpdated(mod);
-                Node before = mod.getDataBefore();
-                if (updated != null && before != null) {
-                    List<LocalMcastMacs> macListUpdated = null;
-                    List<LocalMcastMacs> macListBefore = null;
-                    HwvtepGlobalAugmentation hgUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgUpdated != null) {
-                        macListUpdated = hgUpdated.getLocalMcastMacs();
-                    }
-                    HwvtepGlobalAugmentation hgBefore = before.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgBefore != null) {
-                        macListBefore = hgBefore.getLocalMcastMacs();
-                    }
-                    if (macListBefore != null) {
-                        List<LocalMcastMacs> macListRemoved = new ArrayList<LocalMcastMacs>();
-                        if (macListUpdated != null) {
-                            macListBefore.removeAll(macListUpdated);
-                        }
-                        //then exclude updated localMcastMacs
-                        if (macListUpdated != null) {
-                            for (LocalMcastMacs macBefore : macListBefore) {
-                                int i = 0;
-                                for (; i < macListUpdated.size(); i++) {
-                                    if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
-                                        break;
-                                    }
-                                }
-                                if (i == macListUpdated.size()) {
-                                    macListRemoved.add(macBefore);
-                                }
-                            }
-                        } else {
-                            macListRemoved.addAll(macListBefore);
-                        }
-                        if (!macListRemoved.isEmpty()) {
-                            result.put(key, macListRemoved);
-                        }
-                    }
-                }
-            }
+    @Override
+    protected List<LocalMcastMacs> getData(HwvtepGlobalAugmentation augmentation) {
+        return augmentation.getLocalMcastMacs();
+    }
+
+    @Override
+    protected boolean cascadeDelete() {
+        return true;
+    }
+
+    @Override
+    protected UnMetDependencyGetter getDependencyGetter() {
+        return MAC_DEPENDENCY_GETTER;
+    }
+
+    static UnMetDependencyGetter MAC_DEPENDENCY_GETTER = new MacDependencyGetter();
+
+    public static class MacDependencyGetter extends UnMetDependencyGetter<LocalMcastMacs> {
+        public List<InstanceIdentifier<?>> getLogicalSwitchDependencies(LocalMcastMacs data) {
+            return Lists.newArrayList(data.getLogicalSwitchRef().getValue());
+        }
+
+        @Override
+        public List<InstanceIdentifier<?>> getTerminationPointDependencies(LocalMcastMacs data) {
+            return Collections.EMPTY_LIST;
         }
-        return result;
     }
 }
index facfecfaab382edfbb02aa4aa3af0420308f9269..bad6cdd756fad0b556f5ab6327d69b7ee075d94b 100644 (file)
@@ -11,12 +11,10 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
 import org.opendaylight.ovsdb.lib.notation.UUID;
@@ -34,7 +32,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
-public class McastMacsLocalUpdateCommand extends AbstractTransactCommand {
+public class McastMacsLocalUpdateCommand extends AbstractTransactCommand<LocalMcastMacs, HwvtepGlobalAugmentation> {
     private static final Logger LOG = LoggerFactory.getLogger(McastMacsLocalUpdateCommand.class);
 
     public McastMacsLocalUpdateCommand(HwvtepOperationalState state,
@@ -44,14 +42,6 @@ public class McastMacsLocalUpdateCommand extends AbstractTransactCommand {
 
     @Override
     public void execute(TransactionBuilder transaction) {
-        Map<InstanceIdentifier<Node>, List<LocalMcastMacs>> createds =
-                extractCreated(getChanges(),LocalMcastMacs.class);
-        if (!createds.isEmpty()) {
-            for (Entry<InstanceIdentifier<Node>, List<LocalMcastMacs>> created:
-                createds.entrySet()) {
-                updateMcastMacsLocal(transaction,  created.getKey(), created.getValue());
-            }
-        }
         Map<InstanceIdentifier<Node>, List<LocalMcastMacs>> updateds =
                 extractUpdated(getChanges(),LocalMcastMacs.class);
         if (!updateds.isEmpty()) {
@@ -137,60 +127,8 @@ public class McastMacsLocalUpdateCommand extends AbstractTransactCommand {
         }
     }
 
-    private Map<InstanceIdentifier<Node>, List<LocalMcastMacs>> extractCreated(
-            Collection<DataTreeModification<Node>> changes, Class<LocalMcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<LocalMcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<LocalMcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                Node created = TransactUtils.getCreated(mod);
-                if (created != null) {
-                    List<LocalMcastMacs> macListUpdated = null;
-                    HwvtepGlobalAugmentation hgAugmentation = created.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgAugmentation != null) {
-                        macListUpdated = hgAugmentation.getLocalMcastMacs();
-                    }
-                    if (macListUpdated != null) {
-                        result.put(key, macListUpdated);
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    private Map<InstanceIdentifier<Node>, List<LocalMcastMacs>> extractUpdated(
-            Collection<DataTreeModification<Node>> changes, Class<LocalMcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<LocalMcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<LocalMcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                Node updated = TransactUtils.getUpdated(mod);
-                Node before = mod.getDataBefore();
-                if (updated != null && before != null) {
-                    List<LocalMcastMacs> macListUpdated = null;
-                    List<LocalMcastMacs> macListBefore = null;
-                    HwvtepGlobalAugmentation hgUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgUpdated != null) {
-                        macListUpdated = hgUpdated.getLocalMcastMacs();
-                    }
-                    HwvtepGlobalAugmentation hgBefore = before.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgBefore != null) {
-                        macListBefore = hgBefore.getLocalMcastMacs();
-                    }
-                    if (macListUpdated != null) {
-                        if (macListBefore != null) {
-                            macListUpdated.removeAll(macListBefore);
-                        }
-                        result.put(key, macListUpdated);
-                    }
-                }
-            }
-        }
-        return result;
+    @Override
+    protected List<LocalMcastMacs> getData(HwvtepGlobalAugmentation augmentation) {
+        return augmentation.getLocalMcastMacs();
     }
 }
\ No newline at end of file
index 6ccb81b7a189080588c47483b4ade10338d09f38..95814f61741b47e38f66e8ab69e13c0ac780281b 100644 (file)
@@ -12,14 +12,13 @@ import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
 import java.util.ArrayList;
 import java.util.Collection;
-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.HwvtepSouthboundConstants;
+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;
@@ -33,7 +32,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
-public class McastMacsRemoteRemoveCommand extends AbstractTransactCommand {
+public class McastMacsRemoteRemoveCommand extends AbstractTransactCommand<RemoteMcastMacs, HwvtepGlobalAugmentation> {
     private static final Logger LOG = LoggerFactory.getLogger(McastMacsRemoteRemoveCommand.class);
 
     public McastMacsRemoteRemoveCommand(HwvtepOperationalState state,
@@ -51,6 +50,24 @@ public class McastMacsRemoteRemoveCommand extends AbstractTransactCommand {
                 removeMcastMacRemote(transaction,  removed.getKey(), removed.getValue());
             }
         }
+        //Remove the ones whose locator set got emptied
+        Map<InstanceIdentifier<Node>, List<RemoteMcastMacs>> updated =
+                extractUpdated(getChanges(),RemoteMcastMacs.class);
+        if (!HwvtepSouthboundUtil.isEmptyMap(updated)) {
+            for (Entry<InstanceIdentifier<Node>, List<RemoteMcastMacs>> entry:
+                    updated.entrySet()) {
+                List<RemoteMcastMacs> updatedList = entry.getValue();
+                List<RemoteMcastMacs> tobeRemovedList = new ArrayList<>();
+                if (!HwvtepSouthboundUtil.isEmpty(updatedList)) {
+                    for (RemoteMcastMacs mac: updatedList) {
+                        if (HwvtepSouthboundUtil.isEmpty(mac.getLocatorSet())) {
+                            tobeRemovedList.add(mac);
+                        }
+                    }
+                    removeMcastMacRemote(transaction, entry.getKey(), tobeRemovedList);
+                }
+            }
+        }
     }
 
     private void removeMcastMacRemote(TransactionBuilder transaction,
@@ -75,73 +92,17 @@ public class McastMacsRemoteRemoveCommand extends AbstractTransactCommand {
             }
             InstanceIdentifier<RemoteMcastMacs> macIid = instanceIdentifier.augmentation(HwvtepGlobalAugmentation.class).
                     child(RemoteMcastMacs.class, mac.getKey());
-            updateCurrentTxDeleteData(macIid, mac);
+            updateCurrentTxDeleteData(RemoteMcastMacs.class, macIid, mac);
         }
     }
 
-    private Map<InstanceIdentifier<Node>, List<RemoteMcastMacs>> extractRemoved(
-            Collection<DataTreeModification<Node>> changes, Class<RemoteMcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<RemoteMcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<RemoteMcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                //If the node which remoteMcastMacs belong to is removed, all remoteMcastMacs should be removed too.
-                Node removed = TransactUtils.getRemoved(mod);
-                if (removed != null) {
-                    List<RemoteMcastMacs> macListRemoved = null;
-                    if (removed.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
-                        macListRemoved = removed.getAugmentation(HwvtepGlobalAugmentation.class).getRemoteMcastMacs();
-                    }
-                    if (macListRemoved != null) {
-                        result.put(key, macListRemoved);
-                    }
-                }
-                //If the node which remoteMcastMacs belong to is updated, and remoteMcastMacs may
-                //be created or updated or deleted, we need to get deleted ones.
-                Node updated = TransactUtils.getUpdated(mod);
-                Node before = mod.getDataBefore();
-                if (updated != null && before != null) {
-                    List<RemoteMcastMacs> macListUpdated = null;
-                    List<RemoteMcastMacs> macListBefore = null;
-                    HwvtepGlobalAugmentation hgUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgUpdated != null) {
-                        macListUpdated = hgUpdated.getRemoteMcastMacs();
-                    }
-                    HwvtepGlobalAugmentation hgBefore = before.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgBefore != null) {
-                        macListBefore = hgBefore.getRemoteMcastMacs();
-                    }
-                    if (macListBefore != null) {
-                        List<RemoteMcastMacs> macListRemoved = new ArrayList<RemoteMcastMacs>();
-                        if (macListUpdated != null) {
-                            macListBefore = new ArrayList<>(macListBefore);
-                            macListBefore.removeAll(macListUpdated);
-                        }
-                        //then exclude updated remoteMcastMacs
-                        if (macListUpdated != null) {
-                            for (RemoteMcastMacs macBefore : macListBefore) {
-                                int i = 0;
-                                for (; i < macListUpdated.size(); i++) {
-                                    if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
-                                        break;
-                                    }
-                                }
-                                if (i == macListUpdated.size()) {
-                                    macListRemoved.add(macBefore);
-                                }
-                            }
-                        } else {
-                            macListRemoved.addAll(macListBefore);
-                        }
-                        if (!macListRemoved.isEmpty()) {
-                            result.put(key, macListRemoved);
-                        }
-                    }
-                }
-            }
-        }
-        return result;
+    @Override
+    protected List<RemoteMcastMacs> getData(HwvtepGlobalAugmentation augmentation) {
+        return augmentation.getRemoteMcastMacs();
+    }
+
+    @Override
+    protected boolean areEqual(RemoteMcastMacs a, RemoteMcastMacs b) {
+        return a.getKey().equals(b.getKey()) && Objects.equals(a.getLocatorSet(), b.getLocatorSet());
     }
 }
index 30e40ad66197c6ef42d77758dac29d7a5381afa0..1bb7666ac1979948a241ea920614a8d1eff649c8 100644 (file)
@@ -9,8 +9,17 @@
 package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
 import com.google.common.base.Optional;
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
+import java.util.ArrayList;
+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 com.google.common.collect.Lists;
-import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
@@ -28,17 +37,9 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
-public class McastMacsRemoteUpdateCommand extends AbstractTransactCommand<RemoteMcastMacs> {
+public class McastMacsRemoteUpdateCommand extends AbstractTransactCommand<RemoteMcastMacs, HwvtepGlobalAugmentation> {
     private static final Logger LOG = LoggerFactory.getLogger(McastMacsRemoteUpdateCommand.class);
     private static final McastMacUnMetDependencyGetter MCAST_MAC_DATA_VALIDATOR = new McastMacUnMetDependencyGetter();
 
@@ -49,14 +50,6 @@ public class McastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
 
     @Override
     public void execute(TransactionBuilder transaction) {
-        Map<InstanceIdentifier<Node>, List<RemoteMcastMacs>> createds =
-                extractCreated(getChanges(),RemoteMcastMacs.class);
-        if (!createds.isEmpty()) {
-            for (Entry<InstanceIdentifier<Node>, List<RemoteMcastMacs>> created:
-                createds.entrySet()) {
-                updateMcastMacRemote(transaction,  created.getKey(), created.getValue());
-            }
-        }
         Map<InstanceIdentifier<Node>, List<RemoteMcastMacs>> updateds =
                 extractUpdated(getChanges(),RemoteMcastMacs.class);
         if (!updateds.isEmpty()) {
@@ -70,7 +63,10 @@ public class McastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
     private void updateMcastMacRemote(TransactionBuilder transaction,
             InstanceIdentifier<Node> instanceIdentifier, List<RemoteMcastMacs> macList) {
         for (RemoteMcastMacs mac: macList) {
-            onConfigUpdate(transaction, instanceIdentifier, mac, null);
+            //add / update only if locator set got changed
+            if (!HwvtepSouthboundUtil.isEmpty(mac.getLocatorSet())) {
+                onConfigUpdate(transaction, instanceIdentifier, mac, null);
+            }
         }
     }
 
@@ -161,61 +157,14 @@ public class McastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
         }
     }
 
-    private Map<InstanceIdentifier<Node>, List<RemoteMcastMacs>> extractCreated(
-            Collection<DataTreeModification<Node>> changes, Class<RemoteMcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<RemoteMcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<RemoteMcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                Node created = TransactUtils.getCreated(mod);
-                if (created != null) {
-                    List<RemoteMcastMacs> macListUpdated = null;
-                    HwvtepGlobalAugmentation hgAugmentation = created.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgAugmentation != null) {
-                        macListUpdated = hgAugmentation.getRemoteMcastMacs();
-                    }
-                    if (macListUpdated != null) {
-                        result.put(key, macListUpdated);
-                    }
-                }
-            }
-        }
-        return result;
+    @Override
+    protected List<RemoteMcastMacs> getData(HwvtepGlobalAugmentation augmentation) {
+        return augmentation.getRemoteMcastMacs();
     }
 
-    private Map<InstanceIdentifier<Node>, List<RemoteMcastMacs>> extractUpdated(
-            Collection<DataTreeModification<Node>> changes, Class<RemoteMcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<RemoteMcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<RemoteMcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                Node updated = TransactUtils.getUpdated(mod);
-                Node before = mod.getDataBefore();
-                if (updated != null && before != null) {
-                    List<RemoteMcastMacs> macListUpdated = null;
-                    List<RemoteMcastMacs> macListBefore = null;
-                    HwvtepGlobalAugmentation hgUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgUpdated != null) {
-                        macListUpdated = hgUpdated.getRemoteMcastMacs();
-                    }
-                    HwvtepGlobalAugmentation hgBefore = before.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgBefore != null) {
-                        macListBefore = hgBefore.getRemoteMcastMacs();
-                    }
-                    if (macListUpdated != null) {
-                        if (macListBefore != null) {
-                            macListUpdated.removeAll(macListBefore);
-                        }
-                        result.put(key, macListUpdated);
-                    }
-                }
-            }
-        }
-        return result;
+    @Override
+    protected boolean areEqual(RemoteMcastMacs a, RemoteMcastMacs b) {
+        return a.getKey().equals(b.getKey()) && Objects.equals(a.getLocatorSet(), b.getLocatorSet());
     }
 
     static class McastMacUnMetDependencyGetter extends UnMetDependencyGetter<RemoteMcastMacs> {
index 38cfae9eca60a1e30e8ac402074a28db273c1b4e..dbadaeb02f99c57f826cdf0c995d6f1f659ac499 100644 (file)
@@ -45,8 +45,9 @@ public class PhysicalPortRemoveCommand extends AbstractTransactCommand {
 
     @Override
     public void execute(TransactionBuilder transaction) {
+        //TODO reuse from base class instead of extractRemovedPorts
         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> removeds =
-                extractRemoved(getChanges(),HwvtepPhysicalPortAugmentation.class);
+                extractRemovedPorts(getChanges(), HwvtepPhysicalPortAugmentation.class);
         if (!removeds.isEmpty()) {
             for (Entry<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> removed:
                 removeds.entrySet()) {
@@ -83,7 +84,7 @@ public class PhysicalPortRemoveCommand extends AbstractTransactCommand {
         }
     }
 
-    private Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> extractRemoved(
+    protected Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> extractRemovedPorts(
             Collection<DataTreeModification<Node>> changes, Class<HwvtepPhysicalPortAugmentation> class1) {
         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> result
             = new HashMap<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>>();
index 3ecdd600764ef8d6ee73ca44a5cc9efec61bc259..68ab9df57531700a5256677d4d4dfefa497b00ce 100644 (file)
@@ -61,7 +61,7 @@ public class PhysicalPortUpdateCommand extends AbstractTransactCommand {
             }
         }
         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> updateds =
-                extractUpdated(getChanges(),HwvtepPhysicalPortAugmentation.class);
+                extractUpdatedPorts(getChanges(), HwvtepPhysicalPortAugmentation.class);
         if (!updateds.isEmpty()) {
             for (Entry<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> updated:
                 updateds.entrySet()) {
@@ -217,7 +217,7 @@ public class PhysicalPortUpdateCommand extends AbstractTransactCommand {
         return result;
     }
 
-    private Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> extractUpdated(
+    private Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> extractUpdatedPorts(
             Collection<DataTreeModification<Node>> changes, Class<HwvtepPhysicalPortAugmentation> class1) {
         Map<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>> result
             = new HashMap<InstanceIdentifier<Node>, List<HwvtepPhysicalPortAugmentation>>();
index e728135053fb0d810f230bdeeafc64d5e3d5185b..1f81f3b0403bba237c99aecf09b271e37f2b3cd7 100644 (file)
@@ -43,7 +43,7 @@ public class PhysicalSwitchRemoveCommand extends AbstractTransactCommand {
     @Override
     public void execute(TransactionBuilder transaction) {
         Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> removeds =
-                extractRemoved(getChanges(),PhysicalSwitchAugmentation.class);
+                extractRemovedSwitches(getChanges(),PhysicalSwitchAugmentation.class);
         if (!removeds.isEmpty()) {
             for (Entry<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> removed:
                 removeds.entrySet()) {
@@ -76,7 +76,7 @@ public class PhysicalSwitchRemoveCommand extends AbstractTransactCommand {
         }
     }
 
-    private Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> extractRemoved(
+    private Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> extractRemovedSwitches(
             Collection<DataTreeModification<Node>> changes, Class<PhysicalSwitchAugmentation> class1) {
         Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> result
             = new HashMap<InstanceIdentifier<Node>, PhysicalSwitchAugmentation>();
index e7a33b0ba217a14fdb03864755cb89768c113d81..8d776c275ef809951944cf70bd3f99dfd2ee70b6 100644 (file)
@@ -67,7 +67,7 @@ public class PhysicalSwitchUpdateCommand extends AbstractTransactCommand {
             }
         }
         Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> updated =
-                extractUpdated(getChanges(),PhysicalSwitchAugmentation.class);
+                extractUpdatedSwitches(getChanges(),PhysicalSwitchAugmentation.class);
         if (!updated.isEmpty()) {
             for (Entry<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> physicalSwitchEntry:
                 updated.entrySet()) {
@@ -316,7 +316,7 @@ public class PhysicalSwitchUpdateCommand extends AbstractTransactCommand {
         return result;
     }
 
-    private Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> extractUpdated(
+    private Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> extractUpdatedSwitches(
             Collection<DataTreeModification<Node>> changes, Class<PhysicalSwitchAugmentation> class1) {
         Map<InstanceIdentifier<Node>, PhysicalSwitchAugmentation> result
             = new HashMap<InstanceIdentifier<Node>, PhysicalSwitchAugmentation>();
index 5ea0be4dc646e5af86b9ccd7530a6348c18c986e..ec2fb75f22323aef3059540663105e00250b512a 100644 (file)
@@ -9,10 +9,16 @@
 package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
 import java.util.List;
+import java.util.Map;
 
+import com.google.common.base.Strings;
 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
+import org.opendaylight.ovsdb.lib.operations.Delete;
+import org.opendaylight.ovsdb.lib.operations.Insert;
+import org.opendaylight.ovsdb.lib.operations.Operation;
 import org.opendaylight.ovsdb.lib.operations.OperationResult;
 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
+import org.opendaylight.ovsdb.lib.operations.Update;
 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -38,7 +44,21 @@ public class TransactInvokerImpl implements TransactInvoker {
         if (tb.getOperations().size() > 0) {
             try {
                 List<OperationResult> got = result.get();
-                LOG.debug("OVSDB transaction result: {}", got);
+                LOG.debug("HWVTEP transaction result: {}", got);
+                boolean errorOccured = false;
+                if (got != null && got.size() > 0) {
+                    for (OperationResult opResult : got) {
+                        if (!Strings.isNullOrEmpty(opResult.getError())) {
+                            LOG.error("HWVTEP transaction operation failed {} {}",
+                                    opResult.getError(), opResult.getDetails());
+                            errorOccured = true;
+                        }
+                    }
+                }
+                if (errorOccured) {
+                    connectionInstance.getDeviceInfo().clearInTransitData();
+                    printError(tb);
+                }
             } catch (Exception e) {
                 LOG.warn("Transact execution exception: ", e);
             }
@@ -46,4 +66,35 @@ public class TransactInvokerImpl implements TransactInvoker {
         }
     }
 
+    void printError(TransactionBuilder tb) {
+        StringBuffer sb = new StringBuffer();
+        for (Operation op : tb.getOperations()) {
+            if (op instanceof Insert) {
+                Insert insert = (Insert)op;
+                Map row = insert.getRow();
+                sb.append("insert [");
+                if (row != null) {
+                    for (Object key : row.keySet()) {
+                        sb.append(key + " : "+row.get(key)+" , ");
+                    }
+                }
+                sb.append("]   ");
+            } else if (op instanceof Delete) {
+                Delete delete = (Delete)op;
+                sb.append("delete from " );
+                sb.append(delete.getTableSchema().getName());
+            } else if (op instanceof Update) {
+                Update update = (Update)op;
+                sb.append("update [" );
+                Map row = update.getRow();
+                if (row != null) {
+                    for (Object key : row.keySet()) {
+                        sb.append(key + " : "+row.get(key)+" , ");
+                    }
+                }
+                sb.append("]");
+            }
+        }
+        LOG.error("Failed transaction {}", sb);
+    }
 }
index 711a365ef539ea28a96bdbae3ffe0a98a5b65bed..98400fd3d57949b3a66b90e2003bbca64e80b64c 100644 (file)
@@ -17,6 +17,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
@@ -29,8 +30,11 @@ import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocatorSet;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
 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.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
@@ -147,20 +151,9 @@ public class TransactUtils {
                 HwvtepPhysicalLocatorAugmentation locatorAugmentation = operationalLocatorOptional.get();
                 locatorUuid = new UUID(locatorAugmentation.getPhysicalLocatorUuid().getValue());
             } else {
-                locatorUuid = hwvtepOperationalState.getPhysicalLocatorInFlight(iid);
+                locatorUuid = hwvtepOperationalState.getUUIDFromCurrentTx(TerminationPoint.class, iid);
                 if (locatorUuid == null) {
-                    //if no, get it from config DS and create id
-                    Optional<TerminationPoint> configLocatorOptional =
-                            readNodeFromConfig(hwvtepOperationalState.getReadWriteTransaction(), iid);
-                    if (configLocatorOptional.isPresent()) {
-                        HwvtepPhysicalLocatorAugmentation locatorAugmentation =
-                                configLocatorOptional.get().getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
-                        locatorUuid = TransactUtils.createPhysicalLocator(transaction, locatorAugmentation);
-                        hwvtepOperationalState.setPhysicalLocatorInFlight(iid, locatorUuid);
-                    } else {
-                        LOG.warn("Create or update localMcastMac: No physical locator found in operational datastore!"
-                                + "Its indentifier is {}", locator.getLocatorRef().getValue());
-                    }
+                    locatorUuid = createPhysicalLocator(transaction, hwvtepOperationalState, iid);
                 }
             }
             if (locatorUuid != null) {
@@ -174,6 +167,27 @@ public class TransactUtils {
         return new UUID(locatorSetUuid);
     }
 
+    public static UUID createPhysicalLocator(TransactionBuilder transaction, HwvtepOperationalState operationalState,
+                                             InstanceIdentifier<TerminationPoint> iid) {
+        Optional<TerminationPoint> configLocatorOptional = TransactUtils.readNodeFromConfig(
+                operationalState.getReadWriteTransaction(), iid);
+        HwvtepPhysicalLocatorAugmentationBuilder builder = new HwvtepPhysicalLocatorAugmentationBuilder();
+        HwvtepPhysicalLocatorAugmentation locatorAugmentation = null;
+        if (configLocatorOptional.isPresent()) {
+            locatorAugmentation = configLocatorOptional.get().getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
+        } else {
+            builder.setEncapsulationType(EncapsulationTypeVxlanOverIpv4.class);
+            String tepKey = iid.firstKeyOf(TerminationPoint.class).getTpId().getValue();
+            String ip = tepKey.substring(tepKey.indexOf(":")+1);
+            builder.setDstIp(new IpAddress(ip.toCharArray()));
+            locatorAugmentation = builder.build();
+        }
+        UUID locatorUuid = TransactUtils.createPhysicalLocator(transaction, locatorAugmentation);
+        operationalState.updateCurrentTxData(TerminationPoint.class, iid, locatorUuid);
+        operationalState.getDeviceInfo().markKeyAsInTransit(TerminationPoint.class, iid);
+        return locatorUuid;
+    }
+
     public static UUID createPhysicalLocator(TransactionBuilder transaction, HwvtepPhysicalLocatorAugmentation inputLocator) {
         LOG.debug("Creating a physical locator: {}", inputLocator.getDstIp());
         PhysicalLocator physicalLocator = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(), PhysicalLocator.class);
index 9b1556169a3ad89804effde6e30ad397e2bc95f4..1cec98b0cd0ccdb1875d65bbd9ac1b80cf62848a 100644 (file)
@@ -10,14 +10,13 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import com.google.common.collect.Lists;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
@@ -32,7 +31,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
-public class UcastMacsLocalRemoveCommand extends AbstractTransactCommand {
+public class UcastMacsLocalRemoveCommand extends AbstractTransactCommand<LocalUcastMacs, HwvtepGlobalAugmentation> {
     private static final Logger LOG = LoggerFactory.getLogger(UcastMacsLocalRemoveCommand.class);
 
     public UcastMacsLocalRemoveCommand(HwvtepOperationalState state,
@@ -75,68 +74,32 @@ public class UcastMacsLocalRemoveCommand extends AbstractTransactCommand {
         }
     }
 
-    private Map<InstanceIdentifier<Node>, List<LocalUcastMacs>> extractRemoved(
-            Collection<DataTreeModification<Node>> changes, Class<LocalUcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<LocalUcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<LocalUcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                //If the node which remoteUcastMacs belong to is removed, all remoteUcastMacs should be removed too.
-                Node removed = TransactUtils.getRemoved(mod);
-                if (removed != null) {
-                    List<LocalUcastMacs> macListRemoved = null;
-                    if (removed.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
-                        macListRemoved = removed.getAugmentation(HwvtepGlobalAugmentation.class).getLocalUcastMacs();
-                    }
-                    if (macListRemoved != null) {
-                        result.put(key, macListRemoved);
-                    }
-                }
-                //If the node which remoteUcastMacs belong to is updated, and remoteUcastMacs may
-                //be created or updated or deleted, we need to get deleted ones.
-                Node updated = TransactUtils.getUpdated(mod);
-                Node before = mod.getDataBefore();
-                if (updated != null && before != null) {
-                    List<LocalUcastMacs> macListUpdated = null;
-                    List<LocalUcastMacs> macListBefore = null;
-                    HwvtepGlobalAugmentation hgUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgUpdated != null) {
-                        macListUpdated = hgUpdated.getLocalUcastMacs();
-                    }
-                    HwvtepGlobalAugmentation hgBefore = before.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgBefore != null) {
-                        macListBefore = hgBefore.getLocalUcastMacs();
-                    }
-                    if (macListBefore != null) {
-                        List<LocalUcastMacs> macListRemoved = new ArrayList<LocalUcastMacs>();
-                        if (macListUpdated != null) {
-                            macListBefore.removeAll(macListUpdated);
-                        }
-                        //then exclude updated remoteUcastMacs
-                        if (macListUpdated != null) {
-                            for (LocalUcastMacs macBefore : macListBefore) {
-                                int i = 0;
-                                for (; i < macListUpdated.size(); i++) {
-                                    if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
-                                        break;
-                                    }
-                                }
-                                if (i == macListUpdated.size()) {
-                                    macListRemoved.add(macBefore);
-                                }
-                            }
-                        } else {
-                            macListRemoved.addAll(macListBefore);
-                        }
-                        if (!macListRemoved.isEmpty()) {
-                            result.put(key, macListRemoved);
-                        }
-                    }
-                }
-            }
+    @Override
+    protected List<LocalUcastMacs> getData(HwvtepGlobalAugmentation augmentation) {
+        return augmentation.getLocalUcastMacs();
+    }
+
+    @Override
+    protected boolean cascadeDelete() {
+        return true;
+    }
+
+    @Override
+    protected UnMetDependencyGetter getDependencyGetter() {
+        return MAC_DEPENDENCY_GETTER;
+    }
+
+    static UnMetDependencyGetter MAC_DEPENDENCY_GETTER = new MacDependencyGetter();
+
+    public static class MacDependencyGetter extends UnMetDependencyGetter<LocalUcastMacs> {
+        @Override
+        public List<InstanceIdentifier<?>> getLogicalSwitchDependencies(LocalUcastMacs data) {
+            return Lists.newArrayList(data.getLogicalSwitchRef().getValue());
+        }
+
+        @Override
+        public List<InstanceIdentifier<?>> getTerminationPointDependencies(LocalUcastMacs data) {
+            return Collections.EMPTY_LIST;
         }
-        return result;
     }
 }
\ No newline at end of file
index f9a161e81a1137d3e0c601cb923b14aeac863729..1f5b5cc06cf7d3c5ccbecf9adb31523af9bc7f6b 100644 (file)
@@ -11,12 +11,10 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
@@ -24,11 +22,9 @@ import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
 import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsLocal;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 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.HwvtepNodeName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
 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.LogicalSwitchesKey;
 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.yangtools.yang.binding.InstanceIdentifier;
@@ -37,7 +33,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
-public class UcastMacsLocalUpdateCommand extends AbstractTransactCommand {
+public class UcastMacsLocalUpdateCommand extends AbstractTransactCommand<LocalUcastMacs, HwvtepGlobalAugmentation> {
     private static final Logger LOG = LoggerFactory.getLogger(UcastMacsLocalUpdateCommand.class);
 
     public UcastMacsLocalUpdateCommand(HwvtepOperationalState state,
@@ -47,14 +43,6 @@ public class UcastMacsLocalUpdateCommand extends AbstractTransactCommand {
 
     @Override
     public void execute(TransactionBuilder transaction) {
-        Map<InstanceIdentifier<Node>, List<LocalUcastMacs>> createds =
-                extractCreated(getChanges(),LocalUcastMacs.class);
-        if (!createds.isEmpty()) {
-            for (Entry<InstanceIdentifier<Node>, List<LocalUcastMacs>> created:
-                createds.entrySet()) {
-                updateUcastMacsLocal(transaction,  created.getKey(), created.getValue());
-            }
-        }
         Map<InstanceIdentifier<Node>, List<LocalUcastMacs>> updateds =
                 extractUpdated(getChanges(),LocalUcastMacs.class);
         if (!updateds.isEmpty()) {
@@ -161,60 +149,8 @@ public class UcastMacsLocalUpdateCommand extends AbstractTransactCommand {
         }
     }
 
-    private Map<InstanceIdentifier<Node>, List<LocalUcastMacs>> extractCreated(
-            Collection<DataTreeModification<Node>> changes, Class<LocalUcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<LocalUcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<LocalUcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                Node created = TransactUtils.getCreated(mod);
-                if (created != null) {
-                    List<LocalUcastMacs> macListUpdated = null;
-                    HwvtepGlobalAugmentation hgAugmentation = created.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgAugmentation != null) {
-                        macListUpdated = hgAugmentation.getLocalUcastMacs();
-                    }
-                    if (macListUpdated != null) {
-                        result.put(key, macListUpdated);
-                    }
-                }
-            }
-        }
-        return result;
+    protected List<LocalUcastMacs> getData(HwvtepGlobalAugmentation augmentation) {
+        return augmentation.getLocalUcastMacs();
     }
 
-    private Map<InstanceIdentifier<Node>, List<LocalUcastMacs>> extractUpdated(
-            Collection<DataTreeModification<Node>> changes, Class<LocalUcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<LocalUcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<LocalUcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                Node updated = TransactUtils.getUpdated(mod);
-                Node before = mod.getDataBefore();
-                if (updated != null && before != null) {
-                    List<LocalUcastMacs> macListUpdated = null;
-                    List<LocalUcastMacs> macListBefore = null;
-                    HwvtepGlobalAugmentation hgUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgUpdated != null) {
-                        macListUpdated = hgUpdated.getLocalUcastMacs();
-                    }
-                    HwvtepGlobalAugmentation hgBefore = before.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgBefore != null) {
-                        macListBefore = hgBefore.getLocalUcastMacs();
-                    }
-                    if (macListUpdated != null) {
-                        if (macListBefore != null) {
-                            macListUpdated.removeAll(macListBefore);
-                        }
-                        result.put(key, macListUpdated);
-                    }
-                }
-            }
-        }
-        return result;
-    }
 }
index 16ca422a637448c0eb99290cf2c15c95af6c8bf1..3883fed200f48d2fd6b158ccf182e15c92bc7008 100644 (file)
@@ -10,21 +10,17 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 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.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.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;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -33,7 +29,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
-public class UcastMacsRemoteRemoveCommand extends AbstractTransactCommand {
+public class UcastMacsRemoteRemoveCommand extends AbstractTransactCommand<RemoteUcastMacs, HwvtepGlobalAugmentation> {
     private static final Logger LOG = LoggerFactory.getLogger(UcastMacsRemoteRemoveCommand.class);
 
     public UcastMacsRemoteRemoveCommand(HwvtepOperationalState state,
@@ -75,72 +71,12 @@ public class UcastMacsRemoteRemoveCommand extends AbstractTransactCommand {
             }
             InstanceIdentifier<RemoteUcastMacs> macIid = instanceIdentifier.augmentation(HwvtepGlobalAugmentation.class).
                     child(RemoteUcastMacs.class, mac.getKey());
-            updateCurrentTxDeleteData(macIid, mac);
+            updateCurrentTxDeleteData(RemoteUcastMacs.class, macIid, mac);
         }
     }
 
-    private Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> extractRemoved(
-            Collection<DataTreeModification<Node>> changes, Class<RemoteUcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<RemoteUcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                //If the node which remoteUcastMacs belong to is removed, all remoteUcastMacs should be removed too.
-                Node removed = TransactUtils.getRemoved(mod);
-                if (removed != null) {
-                    List<RemoteUcastMacs> macListRemoved = null;
-                    if (removed.getAugmentation(HwvtepGlobalAugmentation.class) != null) {
-                        macListRemoved = removed.getAugmentation(HwvtepGlobalAugmentation.class).getRemoteUcastMacs();
-                    }
-                    if (macListRemoved != null) {
-                        result.put(key, macListRemoved);
-                    }
-                }
-                //If the node which remoteUcastMacs belong to is updated, and remoteUcastMacs may
-                //be created or updated or deleted, we need to get deleted ones.
-                Node updated = TransactUtils.getUpdated(mod);
-                Node before = mod.getDataBefore();
-                if (updated != null && before != null) {
-                    List<RemoteUcastMacs> macListUpdated = null;
-                    List<RemoteUcastMacs> macListBefore = null;
-                    HwvtepGlobalAugmentation hgUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgUpdated != null) {
-                        macListUpdated = hgUpdated.getRemoteUcastMacs();
-                    }
-                    HwvtepGlobalAugmentation hgBefore = before.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgBefore != null) {
-                        macListBefore = hgBefore.getRemoteUcastMacs();
-                    }
-                    if (macListBefore != null) {
-                        List<RemoteUcastMacs> macListRemoved = new ArrayList<RemoteUcastMacs>();
-                        if (macListUpdated != null) {
-                            macListBefore.removeAll(macListUpdated);
-                        }
-                        //then exclude updated remoteUcastMacs
-                        if (macListUpdated != null) {
-                            for (RemoteUcastMacs macBefore : macListBefore) {
-                                int i = 0;
-                                for (; i < macListUpdated.size(); i++) {
-                                    if (macBefore.getKey().equals(macListUpdated.get(i).getKey())) {
-                                        break;
-                                    }
-                                }
-                                if (i == macListUpdated.size()) {
-                                    macListRemoved.add(macBefore);
-                                }
-                            }
-                        } else {
-                            macListRemoved.addAll(macListBefore);
-                        }
-                        if (!macListRemoved.isEmpty()) {
-                            result.put(key, macListRemoved);
-                        }
-                    }
-                }
-            }
-        }
-        return result;
+    protected List<RemoteUcastMacs> getData(HwvtepGlobalAugmentation augmentation) {
+        return augmentation.getRemoteUcastMacs();
     }
+
 }
index 378fa2e9b14c0105f7b135cfa3c2aa40dd9b57e4..b4de21c848d9167433a09f1ac6799d062131b29a 100644 (file)
@@ -10,15 +10,21 @@ package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
-import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+
+import static org.opendaylight.ovsdb.lib.operations.Operations.op;
+
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4;
 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.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentationBuilder;
 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;
@@ -36,7 +42,7 @@ import java.util.Map.Entry;
 
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
-public class UcastMacsRemoteUpdateCommand extends AbstractTransactCommand<RemoteUcastMacs> {
+public class UcastMacsRemoteUpdateCommand extends AbstractTransactCommand<RemoteUcastMacs, HwvtepGlobalAugmentation> {
     private static final Logger LOG = LoggerFactory.getLogger(UcastMacsRemoteUpdateCommand.class);
     private static final UcastMacUnMetDependencyGetter UCAST_MAC_DATA_VALIDATOR = new UcastMacUnMetDependencyGetter();
 
@@ -47,14 +53,6 @@ public class UcastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
 
     @Override
     public void execute(TransactionBuilder transaction) {
-        Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> createds =
-                extractCreated(getChanges(),RemoteUcastMacs.class);
-        if (!createds.isEmpty()) {
-            for (Entry<InstanceIdentifier<Node>, List<RemoteUcastMacs>> created:
-                createds.entrySet()) {
-                updateUcastMacsRemote(transaction,  created.getKey(), created.getValue());
-            }
-        }
         Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> updateds =
                 extractUpdated(getChanges(),RemoteUcastMacs.class);
         if (!updateds.isEmpty()) {
@@ -151,21 +149,11 @@ public class UcastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
                 HwvtepPhysicalLocatorAugmentation locatorAugmentation = operationalLocatorOptional.get();
                 locatorUuid = new UUID(locatorAugmentation.getPhysicalLocatorUuid().getValue());
             } else {
-                //TODO: need to optimize by eliminating reading Configuration datastore
-                //if no, get it from config DS and create id
-                locatorUuid = getOperationalState().getPhysicalLocatorInFlight(iid);
+                locatorUuid = getOperationalState().getUUIDFromCurrentTx(TerminationPoint.class, iid);
                 if (locatorUuid == null) {
-                    Optional<TerminationPoint> configLocatorOptional =
-                            TransactUtils.readNodeFromConfig(getOperationalState().getReadWriteTransaction(), iid);
-                    if (configLocatorOptional.isPresent()) {
-                        HwvtepPhysicalLocatorAugmentation locatorAugmentation =
-                                configLocatorOptional.get().getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
-                        locatorUuid = TransactUtils.createPhysicalLocator(transaction, locatorAugmentation);
-                        getOperationalState().setPhysicalLocatorInFlight(iid, locatorUuid);
-                    } else {
-                        LOG.warn("Create or update remoteUcastMac: No physical locator found in operational datastore!"
-                                + "Its indentifier is {}", inputMac.getLocatorRef().getValue());
-                    }
+                    locatorUuid = TransactUtils.createPhysicalLocator(transaction, getOperationalState(),
+                            (InstanceIdentifier<TerminationPoint>) inputMac.getLocatorRef().getValue());
+                    updateCurrentTxData(TerminationPoint.class, iid, locatorUuid, null);
                 }
             }
             if (locatorUuid != null) {
@@ -189,61 +177,8 @@ public class UcastMacsRemoteUpdateCommand extends AbstractTransactCommand<Remote
         }
     }
 
-    private Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> extractCreated(
-            Collection<DataTreeModification<Node>> changes, Class<RemoteUcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<RemoteUcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                Node created = TransactUtils.getCreated(mod);
-                if (created != null) {
-                    List<RemoteUcastMacs> macListUpdated = null;
-                    HwvtepGlobalAugmentation hgAugmentation = created.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgAugmentation != null) {
-                        macListUpdated = hgAugmentation.getRemoteUcastMacs();
-                    }
-                    if (macListUpdated != null) {
-                        result.put(key, macListUpdated);
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    private Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> extractUpdated(
-            Collection<DataTreeModification<Node>> changes, Class<RemoteUcastMacs> class1) {
-        Map<InstanceIdentifier<Node>, List<RemoteUcastMacs>> result
-            = new HashMap<InstanceIdentifier<Node>, List<RemoteUcastMacs>>();
-        if (changes != null && !changes.isEmpty()) {
-            for (DataTreeModification<Node> change : changes) {
-                final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
-                final DataObjectModification<Node> mod = change.getRootNode();
-                Node updated = TransactUtils.getUpdated(mod);
-                Node before = mod.getDataBefore();
-                if (updated != null && before != null) {
-                    List<RemoteUcastMacs> macListUpdated = null;
-                    List<RemoteUcastMacs> macListBefore = null;
-                    HwvtepGlobalAugmentation hgUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgUpdated != null) {
-                        macListUpdated = hgUpdated.getRemoteUcastMacs();
-                    }
-                    HwvtepGlobalAugmentation hgBefore = before.getAugmentation(HwvtepGlobalAugmentation.class);
-                    if (hgBefore != null) {
-                        macListBefore = hgBefore.getRemoteUcastMacs();
-                    }
-                    if (macListUpdated != null) {
-                        if (macListBefore != null) {
-                            macListUpdated.removeAll(macListBefore);
-                        }
-                        result.put(key, macListUpdated);
-                    }
-                }
-            }
-        }
-        return result;
+    protected List<RemoteUcastMacs> getData(HwvtepGlobalAugmentation augmentation) {
+        return augmentation.getRemoteUcastMacs();
     }
 
     static class UcastMacUnMetDependencyGetter extends UnMetDependencyGetter<RemoteUcastMacs> {
index 13b25e37a67531aeb1ca4d0d0c0fc9e2e855b512..86d11f37df1ad3095cf9661f635f66a1b6a5b8ff 100644 (file)
@@ -78,9 +78,9 @@ public class HwvtepPhysicalLocatorUpdateCommand extends AbstractTransactionComma
                 } else {
                     transaction.put(LogicalDatastoreType.OPERATIONAL,
                             tpPath, tpBuilder.build());
-                    getOvsdbConnectionInstance().getDeviceInfo().updateDeviceOpData(
-                            TerminationPoint.class, tpPath, pLoc.getUuid(), pLoc);
                 }
+                getOvsdbConnectionInstance().getDeviceInfo().updateDeviceOpData(
+                        TerminationPoint.class, tpPath, pLoc.getUuid(), pLoc);
             }
         }
     }
index 79ba56f70e711e351a72fb744da214c2e0a1a937..08875c74a2adf8c38b92f79b972e42b726d7b358 100644 (file)
@@ -25,10 +25,12 @@ import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvoke
 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvokerImpl;
 import org.opendaylight.ovsdb.lib.OvsdbClient;
 import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo;
-import org.opendaylight.ovsdb.lib.operations.Comment;
+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.Update;
+import org.opendaylight.ovsdb.lib.operations.Where;
 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
@@ -180,12 +182,17 @@ public class DataChangeListenerTestBase extends AbstractDataBrokerTest {
      */
     void resetOperations() {
         insertOpCapture = ArgumentCaptor.forClass(TypedBaseTable.class);
+        Update update = mock(Update.class);
         Insert insert = mock(Insert.class);
+        Delete delete = mock(Delete.class);
+        Where where = mock(Where.class);
+        when(delete.where(any())).thenReturn(where);
         when(insert.withId(any(String.class))).thenReturn(insert);
         Operations.op = PowerMockito.mock(Operations.class);
-        when(Operations.op.comment(any(String.class))).thenReturn(mock(Comment.class));
         when(Operations.op.insert(insertOpCapture.capture())).thenReturn(insert);
-
+        when(Operations.op.update(insertOpCapture.capture())).thenReturn(update);
+        when(update.where(any())).thenReturn(where);
+        when(Operations.op.delete(any())).thenReturn(delete);
         ListenableFuture<List<OperationResult>> ft = mock(ListenableFuture.class);
         transactCaptor = ArgumentCaptor.forClass(List.class);
         when(ovsdbClient.transact(any(DatabaseSchema.class), transactCaptor.capture())).thenReturn(ft);
@@ -206,7 +213,7 @@ public class DataChangeListenerTestBase extends AbstractDataBrokerTest {
         tx.submit();
     }
 
-    void addData(LogicalDatastoreType logicalDatastoreType, Class<? extends DataObject> dataObject,
+    Node addData(LogicalDatastoreType logicalDatastoreType, Class<? extends DataObject> dataObject,
                  String[]... data) {
         NodeBuilder nodeBuilder = prepareNode(nodeIid);
         HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder();
@@ -223,7 +230,43 @@ public class DataChangeListenerTestBase extends AbstractDataBrokerTest {
             TestBuilders.addRemoteMcastMacs(nodeIid, builder, data);
         }
         nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, builder.build());
-        mergeNode(logicalDatastoreType, nodeIid, nodeBuilder);
+        return mergeNode(logicalDatastoreType, nodeIid, nodeBuilder);
+    }
+
+    void deleteData(LogicalDatastoreType logicalDatastoreType, Class<? extends DataObject> dataObject,
+                 String[]... data) {
+        NodeBuilder nodeBuilder = prepareNode(nodeIid);
+        ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
+        HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder();
+        if (LogicalSwitches.class == dataObject) {
+            List<LogicalSwitches> logicalSwitches = TestBuilders.addLogicalSwitches(builder, data);
+
+            for (LogicalSwitches ls : logicalSwitches) {
+                InstanceIdentifier<LogicalSwitches> key = nodeIid.augmentation(HwvtepGlobalAugmentation.class).
+                        child(LogicalSwitches.class, ls.getKey());
+                tx.delete(logicalDatastoreType, key);
+            }
+        }
+        if (TerminationPoint.class == dataObject) {
+            TestBuilders.addGlobalTerminationPoints(nodeBuilder, nodeIid, data);
+        }
+        if (RemoteUcastMacs.class == dataObject) {
+            List<RemoteUcastMacs> macs = TestBuilders.addRemoteUcastMacs(nodeIid, builder, data);
+            for (RemoteUcastMacs mac : macs) {
+                InstanceIdentifier<RemoteUcastMacs> key = nodeIid.augmentation(HwvtepGlobalAugmentation.class).
+                        child(RemoteUcastMacs.class, mac.getKey());
+                tx.delete(logicalDatastoreType, key);
+            }
+        }
+        if (RemoteMcastMacs.class == dataObject) {
+            List<RemoteMcastMacs> macs = TestBuilders.addRemoteMcastMacs(nodeIid, builder, data);
+            for (RemoteMcastMacs mac : macs) {
+                InstanceIdentifier<RemoteMcastMacs> key = nodeIid.augmentation(HwvtepGlobalAugmentation.class).
+                        child(RemoteMcastMacs.class, mac.getKey());
+                tx.delete(logicalDatastoreType, key);
+            }
+        }
+        tx.submit();
     }
 
     NodeBuilder prepareNode(InstanceIdentifier<Node> iid) {
index 1b787c785bd4c53f2d63d9e16dab0212470fe4f4..f4cd1017e19058a96be9fcfbad3d1352b86b96fb 100644 (file)
@@ -9,10 +9,14 @@
 package org.opendaylight.ovsdb.hwvtepsouthbound;
 
 import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Matchers;
-import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependencyQueue;
 import org.opendaylight.ovsdb.lib.operations.Operations;
 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
@@ -22,6 +26,7 @@ import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote;
 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;
 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.powermock.core.classloader.annotations.PrepareForTest;
@@ -29,6 +34,8 @@ import org.powermock.modules.junit4.PowerMockRunner;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 import java.util.Iterator;
 import java.util.List;
 
@@ -73,6 +80,45 @@ public class HwvtepDataChangeListenerTest extends DataChangeListenerTestBase {
             {"FF:FF:FF:FF:FF:FF", "ls1", "192.168.122.10", "192.168.122.30"}
     };
 
+    String[][] mcastMac2 = new String[][]{
+            {"FF:FF:FF:FF:FF:FF", "ls0", "192.168.122.20", "192.168.122.10"},
+            {"FF:FF:FF:FF:FF:FF", "ls1", "192.168.122.10", "192.168.122.20"}
+    };
+
+    String[][] mcastMac3WithZeroLocators = new String[][]{
+            {"FF:FF:FF:FF:FF:FF", "ls0"},
+            {"FF:FF:FF:FF:FF:FF", "ls1"}
+    };
+
+    HwvtepOperationalDataChangeListener opDataChangeListener;
+
+    @Before
+    public void setupListener() throws Exception {
+        setFinalStatic(DependencyQueue.class, "executorService", MoreExecutors.sameThreadExecutor());
+        opDataChangeListener = new HwvtepOperationalDataChangeListener(dataBroker, hwvtepConnectionManager, connectionInstance);
+    }
+
+    @After
+    public void cleanupListener() {
+        try {
+            opDataChangeListener.close();
+        } catch (Exception e) {
+        }
+    }
+
+    void setFinalStatic(Class cls, String fieldName, Object newValue) throws Exception {
+        Field fields[] = FieldUtils.getAllFields(cls);
+        for (Field field : fields) {
+            if (fieldName.equals(field.getName())) {
+                field.setAccessible(true);
+                Field modifiersField = Field.class.getDeclaredField("modifiers");
+                modifiersField.setAccessible(true);
+                modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+                field.set(null, newValue);
+                break;
+            }
+        }
+    }
 
     @Test
     public <T extends DataObject> void testLogicalSwitchAdd() throws Exception {
@@ -80,12 +126,19 @@ public class HwvtepDataChangeListenerTest extends DataChangeListenerTestBase {
         verifyThatLogicalSwitchCreated();
     }
 
+    @Test
+    public <T extends DataObject> void testLogicalSwitchDelete() throws Exception {
+        addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
+        addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
+        resetOperations();
+        deleteData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
+        verify(Operations.op,  times(2)).delete(any());
+    }
+
     @Test
     public <T extends DataObject> void testUcastMacAdd() throws Exception {
         addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
-        connectionInstance.getDeviceInfo().updateDeviceOpData(LogicalSwitches.class, ls0Iid, new UUID("ls0"), "ls0");
-        connectionInstance.getDeviceInfo().updateDeviceOpData(LogicalSwitches.class, ls1Iid, new UUID("ls1"), "ls1");
         resetOperations();
         addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
         addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
@@ -94,12 +147,36 @@ public class HwvtepDataChangeListenerTest extends DataChangeListenerTestBase {
         //TODO add finer grained validation
     }
 
+    @Test
+    public <T extends DataObject> void testUcastMacAddWithoutConfigTep() throws Exception {
+        addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
+        addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
+        resetOperations();
+        addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
+        //4 ucast macs + 2 termination points
+        verify(Operations.op,  times(6)).insert(any(UcastMacsRemote.class));
+        //TODO add finer grained validation
+    }
+
+    @Test
+    public <T extends DataObject> void testUcastMacDelete() throws Exception {
+        addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
+        addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
+        addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
+        addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
+        addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
+        addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
+
+        resetOperations();
+        deleteData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
+        verify(Operations.op,  times(4)).delete(any());
+        //TODO add finer grained validation
+    }
+
     @Test
     public <T extends DataObject> void testMcastMacAdd() throws Exception {
         addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
-        connectionInstance.getDeviceInfo().updateDeviceOpData(LogicalSwitches.class, ls0Iid, new UUID("ls0"), "ls0");
-        connectionInstance.getDeviceInfo().updateDeviceOpData(LogicalSwitches.class, ls1Iid, new UUID("ls1"), "ls0");
         resetOperations();
         addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
@@ -108,11 +185,33 @@ public class HwvtepDataChangeListenerTest extends DataChangeListenerTestBase {
     }
 
     @Test
-    public <T extends DataObject> void testAddMacs() throws Exception {
+    public <T extends DataObject> void testMcastMacAddWithoutConfigTep() throws Exception {
         addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
         addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
-        connectionInstance.getDeviceInfo().updateDeviceOpData(LogicalSwitches.class, ls0Iid, new UUID("ls0"), "ls0");
-        connectionInstance.getDeviceInfo().updateDeviceOpData(LogicalSwitches.class, ls1Iid, new UUID("ls1"), "ls0");
+        resetOperations();
+        addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
+        //2 mcast macs + 2 locator sets + 3 termination points
+        verify(Operations.op,  times(7)).insert(Matchers.<McastMacsRemote>any());
+    }
+
+    @Test
+    public <T extends DataObject> void testMcastMacDelete() throws Exception {
+        addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
+        addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
+        addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
+        addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
+        addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
+        addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
+
+        resetOperations();
+        deleteData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
+        verify(Operations.op,  times(2)).delete(Matchers.any());
+    }
+
+    @Test
+    public <T extends DataObject> void testAddMacs() throws Exception {
+        Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
+        addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
         resetOperations();
         addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
         addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
@@ -120,11 +219,83 @@ public class HwvtepDataChangeListenerTest extends DataChangeListenerTestBase {
 
         addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
         addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
+        resetOperations();
+        addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
+        //2 mcast mac + 2 locator sets ( termination point already added )
+        verify(Operations.op,  times(4)).insert(Matchers.<McastMacsRemote>any());
+    }
+
+    @Test
+    public <T extends DataObject> void testUpdateMacs() throws Exception {
+        Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
+        addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
+        resetOperations();
+        addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
+        addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
+        verify(Operations.op,  times(6)).insert(any(UcastMacsRemote.class));
+
+        addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
+        addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
+        resetOperations();
+        addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
+        verify(Operations.op,  times(4)).insert(Matchers.<McastMacsRemote>any());
+        addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
+
+        resetOperations();
+        addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac2);
+        verify(Operations.op,  times(2)).insert(Matchers.<McastMacsRemote>any());
+        verify(Operations.op,  times(2)).update(Matchers.<McastMacsRemote>any());
+        verify(Operations.op,  times(0)).delete(Matchers.any());
+    }
+
+    @Test
+    public <T extends DataObject> void testUpdateMacsWithZeroLocators() throws Exception {
+        Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
+        addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
+        resetOperations();
+        addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
+        addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
+        verify(Operations.op,  times(6)).insert(any(UcastMacsRemote.class));
+
+        addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
+        addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
+        resetOperations();
+        addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
+        verify(Operations.op,  times(4)).insert(Matchers.<McastMacsRemote>any());
+        addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
+
+        resetOperations();
+        addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac3WithZeroLocators);
+        verify(Operations.op,  times(2)).delete(Matchers.any());
+    }
+
+    @Test
+    public <T extends DataObject> void testBackToBackMacsUpdate() throws Exception {
+        Node node = addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches);
+        addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches);
+        resetOperations();
+        addData(CONFIGURATION, TerminationPoint.class, terminationPoints);
+        addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs);
+        verify(Operations.op,  times(6)).insert(any(UcastMacsRemote.class));
 
         resetOperations();
         addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs);
         //2 mcast mac + 2 locator sets ( termination point already added )
+        verify(Operations.op,  times(0)).insert(Matchers.<McastMacsRemote>any());
+        resetOperations();
+        addData(OPERATIONAL, TerminationPoint.class, terminationPoints);
+        addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs);
+        connectionInstance.getDeviceInfo().onOpDataAvailable();
+        //2 mcast mac + 2 locator sets ( termination point already added )
         verify(Operations.op,  times(4)).insert(Matchers.<McastMacsRemote>any());
+
+        resetOperations();
+        addData(CONFIGURATION, RemoteMcastMacs.class, mcastMac2);
+        verify(Operations.op,  times(0)).insert(Matchers.<McastMacsRemote>any());
+        addData(OPERATIONAL, RemoteMcastMacs.class, mcastMacs);
+        connectionInstance.getDeviceInfo().onOpDataAvailable();
+        verify(Operations.op,  times(2)).insert(Matchers.<McastMacsRemote>any());
+        verify(Operations.op,  times(2)).update(Matchers.<McastMacsRemote>any());
     }
 
     private void verifyThatLogicalSwitchCreated() {
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepOperationalDataChangeListener.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepOperationalDataChangeListener.java
new file mode 100644 (file)
index 0000000..d139a5c
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * 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 org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+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.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.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+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.Collection;
+
+public class HwvtepOperationalDataChangeListener implements ClusteredDataTreeChangeListener<Node>, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HwvtepOperationalDataChangeListener.class);
+
+    private final ListenerRegistration<HwvtepOperationalDataChangeListener> registration;
+    private final HwvtepConnectionManager hcm;
+    private final DataBroker db;
+    private final HwvtepConnectionInstance connectionInstance;
+
+    HwvtepOperationalDataChangeListener(DataBroker db, HwvtepConnectionManager hcm, HwvtepConnectionInstance connectionInstance) {
+        this.db = db;
+        this.hcm = hcm;
+        this.connectionInstance = connectionInstance;
+        DataTreeIdentifier<Node> treeId =
+                new DataTreeIdentifier<Node>(LogicalDatastoreType.OPERATIONAL, getWildcardPath());
+        registration = db.registerDataTreeChangeListener(treeId, HwvtepOperationalDataChangeListener.this);
+    }
+
+    @Override
+    public void close() throws Exception {
+        if(registration != null) {
+            registration.close();
+        }
+    }
+
+    @Override
+    public void onDataTreeChanged(Collection<DataTreeModification<Node>> changes) {
+        for (DataTreeModification<Node> change : changes) {
+            final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+            final DataObjectModification<Node> mod = change.getRootNode();
+            for (DataObjectModification<? extends DataObject> child : mod.getModifiedChildren()) {
+                updateDeviceOpData(key, child);
+            }
+            DataObjectModification<HwvtepGlobalAugmentation> aug = mod.getModifiedAugmentation(HwvtepGlobalAugmentation.class);
+            if (aug != null && getModificationType(aug) != null) {
+                Collection<DataObjectModification<? extends DataObject>> children = aug.getModifiedChildren();
+                for (DataObjectModification<? extends DataObject> child : children) {
+                    updateDeviceOpData(key, child);
+                }
+            }
+        }
+    }
+
+    private void updateDeviceOpData(InstanceIdentifier<Node> key, DataObjectModification<? extends DataObject> mod) {
+        ModificationType type = getModificationType(mod);
+        if (type == null) {
+            return;
+        }
+        Class<? extends Identifiable> childClass = (Class<? extends Identifiable>) mod.getDataType();
+        InstanceIdentifier instanceIdentifier = getKey(key, mod, mod.getDataAfter());
+        switch(type) {
+            case WRITE:
+                connectionInstance.getDeviceInfo().updateDeviceOpData(childClass, instanceIdentifier,
+                        new UUID("uuid"), mod.getDataAfter());
+                break;
+            case DELETE:
+                connectionInstance.getDeviceInfo().clearDeviceOpData(childClass, instanceIdentifier);
+                break;
+            case SUBTREE_MODIFIED:
+        }
+    }
+
+    private ModificationType getModificationType(DataObjectModification<? extends DataObject> mod) {
+        try {
+            return mod.getModificationType();
+        } catch (IllegalStateException e) {
+            LOG.debug("Failed to get the modification type ", e);
+        }
+        return null;
+    }
+
+    private InstanceIdentifier getKey(InstanceIdentifier<Node> key, DataObjectModification<? extends DataObject> child,
+                                      DataObject data) {
+        Class<? extends DataObject> childClass = child.getDataType();
+        InstanceIdentifier instanceIdentifier = null;
+        if (LogicalSwitches.class == childClass) {
+            LogicalSwitches ls = (LogicalSwitches)data;
+            instanceIdentifier = key.augmentation(HwvtepGlobalAugmentation.class).child(LogicalSwitches.class, ls.getKey());
+        } else if (org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint.class == childClass) {
+            TerminationPoint tp = (TerminationPoint)data;
+            instanceIdentifier = key.child(TerminationPoint.class, tp.getKey());
+        } else if (RemoteUcastMacs.class == childClass) {
+            RemoteUcastMacs mac = (RemoteUcastMacs)data;
+            instanceIdentifier = key.augmentation(HwvtepGlobalAugmentation.class).child(RemoteUcastMacs.class, mac.getKey());
+        } else if (RemoteMcastMacs.class ==  childClass) {
+            RemoteMcastMacs mac = (RemoteMcastMacs)data;
+            instanceIdentifier = key.augmentation(HwvtepGlobalAugmentation.class).child(RemoteMcastMacs.class, mac.getKey());
+        }
+        return instanceIdentifier;
+    }
+
+    Class<? extends ChildOf<? super HwvtepGlobalAugmentation>> getClass(Class<? extends DataObject> cls) {
+        return (Class<? extends ChildOf<? super HwvtepGlobalAugmentation>>) cls;
+    }
+
+    private InstanceIdentifier<Node> getWildcardPath() {
+        InstanceIdentifier<Node> path = InstanceIdentifier
+                        .create(NetworkTopology.class)
+                        .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
+                        .child(Node.class);
+        return path;
+    }
+}
index 25628546e4fa26d1f4aea571c9fb318cc3299fd3..2290920b1de60a0517c47978a41e523b4d665d51 100644 (file)
@@ -44,15 +44,16 @@ public class TestBuilders {
 
     public static final String VXLAN_OVER_IPV4 = "vxlan_over_ipv4";
 
-    public static void addLogicalSwitches(HwvtepGlobalAugmentationBuilder augmentationBuilder, String[]... data) {
+    public static List<LogicalSwitches> addLogicalSwitches(HwvtepGlobalAugmentationBuilder augmentationBuilder, String[]... data) {
         List<LogicalSwitches> logicalSwitcheses = Lists.newArrayList();
         for (String row[] : data) {
             logicalSwitcheses.add(TestBuilders.buildLogicalSwitch(row));
         }
         augmentationBuilder.setLogicalSwitches(logicalSwitcheses);
+        return logicalSwitcheses;
     }
 
-    public static void addRemoteMcastMacs(InstanceIdentifier<Node> iid,
+    public static List<RemoteMcastMacs> addRemoteMcastMacs(InstanceIdentifier<Node> iid,
                                           HwvtepGlobalAugmentationBuilder augmentationBuilder, String[]... data) {
         List<RemoteMcastMacs> remoteMcastMacses = Lists.newArrayList();
         for (String row[] : data) {
@@ -60,6 +61,7 @@ public class TestBuilders {
             remoteMcastMacses.add(TestBuilders.buildRemoteMcastMacs(iid, row[0], row[1], teps));
         }
         augmentationBuilder.setRemoteMcastMacs(remoteMcastMacses);
+        return remoteMcastMacses;
     }
 
     public static List<RemoteUcastMacs> addRemoteUcastMacs(InstanceIdentifier<Node> iid,
index 3d34523f77e042e6c644ba42e91782c108840e7c..dfb9d31ca60ea89a1f5233b0831ddbed24b6e0b5 100644 (file)
           "ipaddr": {
             "type": "string"
           },
+          "_uuid": {
+            "type": "string"
+          },
           "locator_set": {
             "type": {
               "key": {
           "ipaddr": {
             "type": "string"
           },
+          "_uuid": {
+            "type": "string"
+          },
           "locator_set": {
             "type": {
               "key": {
             }
           }
         },
+        "_uuid": {
+          "type": "string"
+        },
         "indexes": [
           [
             "encapsulation_type",
       },
       "Physical_Locator_Set": {
         "columns": {
+          "_uuid": {
+            "type": "string"
+          },
           "locators": {
             "mutable": false,
             "type": {
           "description": {
             "type": "string"
           },
+          "_uuid": {
+            "type": "string"
+          },
           "name": {
             "type": "string"
           },
           "description": {
             "type": "string"
           },
+          "_uuid": {
+            "type": "string"
+          },
           "management_ips": {
             "type": {
               "key": "string",
           "ipaddr": {
             "type": "string"
           },
+          "_uuid": {
+            "type": "string"
+          },
           "locator": {
             "type": {
               "key": {
           "ipaddr": {
             "type": "string"
           },
+          "_uuid": {
+            "type": "uuid"
+          },
+          "uuid": {
+            "type": "uuid"
+          },
           "locator": {
             "type": {
               "key": {