Bug 6374 topology-manager - DTCL instead of DTL 30/43530/9
authorAndrej Leitner <andrej.leitner@pantheon.tech>
Tue, 9 Aug 2016 16:15:02 +0000 (18:15 +0200)
committerAndrej Leitner <andrej.leitner@pantheon.sk>
Mon, 15 Aug 2016 11:51:17 +0000 (11:51 +0000)
 - topology-manager app converted to use DataTreeChangeListener
   instead of deprecated DataChangeListener
 - updated tests

Change-Id: Ibc242d4dbd4238153813762bd8ed56510ccf2706
Signed-off-by: Andrej Leitner <andrej.leitner@pantheon.tech>
applications/topology-manager/pom.xml
applications/topology-manager/src/main/java/org/opendaylight/openflowplugin/applications/topology/manager/DataChangeListenerImpl.java
applications/topology-manager/src/main/java/org/opendaylight/openflowplugin/applications/topology/manager/NodeChangeListenerImpl.java
applications/topology-manager/src/main/java/org/opendaylight/openflowplugin/applications/topology/manager/TerminationPointChangeListenerImpl.java
applications/topology-manager/src/test/java/org/opendaylight/openflowplugin/applications/topology/manager/DataChangeListenerBase.java
applications/topology-manager/src/test/java/org/opendaylight/openflowplugin/applications/topology/manager/NodeChangeListenerImplTest.java
applications/topology-manager/src/test/java/org/opendaylight/openflowplugin/applications/topology/manager/TerminationPointChangeListenerImplTest.java
applications/topology-manager/src/test/java/org/opendaylight/openflowplugin/applications/topology/manager/TestUtils.java
applications/topology-manager/src/test/resources/log4j.xml [new file with mode: 0644]

index 35513f8d691dcae7a83d0b6a78d8af2f3163bce1..0f007a0863b0e5850158ddd310c79b9c9d88f33c 100644 (file)
       <artifactId>mockito-all</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
   <scm>
     <connection>scm:git:ssh://git.opendaylight.org:29418/openflowplugin.git</connection>
index a7713430f5b33ad0c23e02b7b4faf745860eee86..3a28868fa289a58d9b3d93f036e278ed1b461b3d 100644 (file)
@@ -9,9 +9,9 @@ package org.opendaylight.openflowplugin.applications.topology.manager;
 
 import java.util.concurrent.Callable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
@@ -27,12 +27,12 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public abstract class DataChangeListenerImpl implements DataChangeListener, AutoCloseable {
+public abstract class DataChangeListenerImpl<T extends DataObject> implements DataTreeChangeListener<T>, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(DataChangeListenerImpl.class);
     private static final long STARTUP_LOOP_TICK = 500L;
     private static final int STARTUP_LOOP_MAX_RETRIES = 8;
-    protected final ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+    protected final ListenerRegistration<DataTreeChangeListener> dataChangeListenerRegistration;
     protected OperationProcessor operationProcessor;
 
     /**
@@ -40,32 +40,25 @@ public abstract class DataChangeListenerImpl implements DataChangeListener, Auto
      */
     protected static final InstanceIdentifier<Topology> II_TO_TOPOLOGY =
             InstanceIdentifier
-            .builder(NetworkTopology.class)
-            .child(Topology.class, new TopologyKey(new TopologyId(FlowCapableTopologyProvider.TOPOLOGY_ID)))
-            .build();
+            .create(NetworkTopology.class)
+            .child(Topology.class, new TopologyKey(new TopologyId(FlowCapableTopologyProvider.TOPOLOGY_ID)));
 
-
-    /**
-     *
-     */
-    public DataChangeListenerImpl(final OperationProcessor operationProcessor, final DataBroker dataBroker,
-            final InstanceIdentifier<?> ii) {
-        SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
+    public DataChangeListenerImpl(final OperationProcessor operationProcessor,
+                                  final DataBroker dataBroker,
+                                  final InstanceIdentifier<T> ii) {
+        final DataTreeIdentifier<T> identifier = new DataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, ii);
+        final SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
         try {
-            dataChangeListenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<DataChangeListener>>() {
+            dataChangeListenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<DataTreeChangeListener>>() {
                 @Override
-                public ListenerRegistration<DataChangeListener> call() throws Exception {
-                    return dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, ii,
-                            DataChangeListenerImpl.this, AsyncDataBroker.DataChangeScope.BASE);
-
+                public ListenerRegistration<DataTreeChangeListener> call() throws Exception {
+                    return dataBroker.registerDataTreeChangeListener(identifier, DataChangeListenerImpl.this);
                 }
             });
         } catch (Exception e) {
-            LOG.warn("data listener registration failed: {}", e.getMessage());
-            LOG.debug("data listener registration failed.. ", e);
+            LOG.error("Data listener registration failed!");
             throw new IllegalStateException("TopologyManager startup fail! TM bundle needs restart.", e);
         }
-
         this.operationProcessor = operationProcessor;
     }
 
@@ -74,10 +67,8 @@ public abstract class DataChangeListenerImpl implements DataChangeListener, Auto
         dataChangeListenerRegistration.close();
     }
 
-    protected <T extends DataObject> void sendToTransactionChain(final T node,
-            final InstanceIdentifier<T> iiToTopologyNode) {
+    protected <T extends DataObject> void sendToTransactionChain(final T node, final InstanceIdentifier<T> iiToTopologyNode) {
         operationProcessor.enqueueOperation(new TopologyOperation() {
-
             @Override
             public void applyOperation(ReadWriteTransaction transaction) {
                 transaction.merge(LogicalDatastoreType.OPERATIONAL, iiToTopologyNode, node, true);
@@ -95,7 +86,7 @@ public abstract class DataChangeListenerImpl implements DataChangeListener, Auto
                         nodeKeyInTopology).build();
     }
 
-    protected NodeId provideTopologyNodeId(InstanceIdentifier<?> iiToNodeInInventory) {
+    protected NodeId provideTopologyNodeId(InstanceIdentifier<T> iiToNodeInInventory) {
         final NodeKey inventoryNodeKey = iiToNodeInInventory.firstKeyOf(Node.class, NodeKey.class);
         if (inventoryNodeKey != null) {
             return new NodeId(inventoryNodeKey.getId().getValue());
index b0ed434bb4d5449c1c02f69396c4edd390845fbb..473f23d1bcf5b3508e45ed2f454692b0139b4d9a 100644 (file)
@@ -7,12 +7,11 @@
  */
 package org.opendaylight.openflowplugin.applications.topology.manager;
 
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
+import java.util.Collection;
+import javax.annotation.Nonnull;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
@@ -22,69 +21,58 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class NodeChangeListenerImpl extends DataChangeListenerImpl {
+public class NodeChangeListenerImpl extends DataChangeListenerImpl<FlowCapableNode> {
     private static final Logger LOG = LoggerFactory.getLogger(NodeChangeListenerImpl.class);
 
     public NodeChangeListenerImpl(final DataBroker dataBroker, final OperationProcessor operationProcessor) {
-        // TODO: listener on FlowCapableNode. what if node id in Node.class is changed (it won't be caught by this
-        // listener)
+        // TODO: listener on FlowCapableNode. what if node id in Node.class is changed (it won't be caught by this listener)
         super(operationProcessor, dataBroker, InstanceIdentifier.builder(Nodes.class).child(Node.class)
                 .augmentation(FlowCapableNode.class).build());
     }
 
     @Override
-    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-        processAddedNode(change.getCreatedData());
-        // processUpdatedNode(change.getUpdatedData());
-        processRemovedNode(change.getRemovedPaths());
-    }
-
-    /**
-     * @param removedNodes
-     */
-    private void processRemovedNode(final Set<InstanceIdentifier<?>> removedNodes) {
-        for (InstanceIdentifier<?> removedNode : removedNodes) {
-            final NodeId nodeId = provideTopologyNodeId(removedNode);
-            final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> iiToTopologyRemovedNode = provideIIToTopologyNode(nodeId);
-            if (iiToTopologyRemovedNode != null) {
-                operationProcessor.enqueueOperation(new TopologyOperation() {
-
-                    @Override
-                    public void applyOperation(final ReadWriteTransaction transaction) {
-                        transaction.delete(LogicalDatastoreType.OPERATIONAL, iiToTopologyRemovedNode);
-                        TopologyManagerUtil.removeAffectedLinks(nodeId, transaction, II_TO_TOPOLOGY);
-                    }
-                });
-            } else {
-                LOG.debug("Instance identifier to inventory wasn't translated to topology while deleting node.");
+    public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<FlowCapableNode>> modifications) {
+        for (DataTreeModification modification : modifications) {
+            switch (modification.getRootNode().getModificationType()) {
+                case WRITE:
+                    processAddedNode(modification);
+                    break;
+                case SUBTREE_MODIFIED:
+                    // NOOP
+                    break;
+                case DELETE:
+                    processRemovedNode(modification);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unhandled modification type: {}" +
+                            modification.getRootNode().getModificationType());
             }
         }
     }
 
-//    /**
-//     * @param updatedData
-//     */
-//     private void processUpdatedNode(Map<InstanceIdentifier<?>, DataObject> updatedData) {
-//         //TODO: only node id is used from incoming data object.
-//         //if it is changed what should happen? Listener is on FlowCapableNode so change
-//         //of node id (only data which are used) isn't caught.
-//     }
-
-    /**
-     * @param addedDatas
-     */
-    private void processAddedNode(final Map<InstanceIdentifier<?>, DataObject> addedDatas) {
-        for (Entry<InstanceIdentifier<?>, DataObject> addedData : addedDatas.entrySet()) {
-            createData(addedData.getKey());
+    private void processRemovedNode(final DataTreeModification<FlowCapableNode> modification) {
+        final InstanceIdentifier<FlowCapableNode> iiToNodeInInventory = modification.getRootPath().getRootIdentifier();
+        final NodeId nodeId = provideTopologyNodeId(iiToNodeInInventory);
+        final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> iiToTopologyRemovedNode = provideIIToTopologyNode(nodeId);
+        if (iiToTopologyRemovedNode != null) {
+            operationProcessor.enqueueOperation(new TopologyOperation() {
+                @Override
+                public void applyOperation(final ReadWriteTransaction transaction) {
+                    transaction.delete(LogicalDatastoreType.OPERATIONAL, iiToTopologyRemovedNode);
+                    TopologyManagerUtil.removeAffectedLinks(nodeId, transaction, II_TO_TOPOLOGY);
+                }
+            });
+        } else {
+            LOG.debug("Instance identifier to inventory wasn't translated to topology while deleting node.");
         }
     }
 
-    protected void createData(final InstanceIdentifier<?> iiToNodeInInventory) {
+    private void processAddedNode(final DataTreeModification<FlowCapableNode> modification) {
+        final InstanceIdentifier<FlowCapableNode> iiToNodeInInventory = modification.getRootPath().getRootIdentifier();
         final NodeId nodeIdInTopology = provideTopologyNodeId(iiToNodeInInventory);
         if (nodeIdInTopology != null) {
             final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> iiToTopologyNode = provideIIToTopologyNode(nodeIdInTopology);
@@ -94,15 +82,11 @@ public class NodeChangeListenerImpl extends DataChangeListenerImpl {
         }
     }
 
-    /**
-     * @param nodeIdInTopology
-     * @param iiToNodeInInventory
-     * @return Node
-     */
-    private static org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node prepareTopologyNode(final NodeId nodeIdInTopology, final InstanceIdentifier<?> iiToNodeInInventory) {
+    private static org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node
+    prepareTopologyNode(final NodeId nodeIdInTopology, final InstanceIdentifier<FlowCapableNode> iiToNodeInInventory) {
         final InventoryNode inventoryNode = new InventoryNodeBuilder()
-        .setInventoryNodeRef(new NodeRef(iiToNodeInInventory.firstIdentifierOf(Node.class)))
-        .build();
+            .setInventoryNodeRef(new NodeRef(iiToNodeInInventory.firstIdentifierOf(Node.class)))
+            .build();
 
         final NodeBuilder topologyNodeBuilder = new NodeBuilder();
         topologyNodeBuilder.setNodeId(nodeIdInTopology);
@@ -110,4 +94,5 @@ public class NodeChangeListenerImpl extends DataChangeListenerImpl {
 
         return topologyNodeBuilder.build();
     }
+
 }
\ No newline at end of file
index 998c23c1722538834953fbf727f7775f2d08885b..f2bb85752aeca7a6e8ba61f278035a58413c6367 100644 (file)
@@ -8,12 +8,11 @@
 package org.opendaylight.openflowplugin.applications.topology.manager;
 
 import com.google.common.base.Optional;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
+import java.util.Collection;
+import javax.annotation.Nonnull;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
@@ -29,12 +28,11 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class TerminationPointChangeListenerImpl extends DataChangeListenerImpl {
+public class TerminationPointChangeListenerImpl extends DataChangeListenerImpl<FlowCapableNodeConnector> {
     private static final Logger LOG = LoggerFactory.getLogger(TerminationPointChangeListenerImpl.class);
 
     public TerminationPointChangeListenerImpl(final DataBroker dataBroker, final OperationProcessor operationProcessor) {
@@ -44,82 +42,74 @@ public class TerminationPointChangeListenerImpl extends DataChangeListenerImpl {
     }
 
     @Override
-    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
-        processAddedTerminationPoints(change.getCreatedData());
-        processUpdatedTerminationPoints(change.getUpdatedData());
-        processRemovedTerminationPoints(change.getRemovedPaths());
+    public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<FlowCapableNodeConnector>> modifications) {
+        for (DataTreeModification<FlowCapableNodeConnector> modification : modifications) {
+            switch (modification.getRootNode().getModificationType()) {
+                case WRITE:
+                    processAddedTerminationPoints(modification);
+                    break;
+                case SUBTREE_MODIFIED:
+                    processUpdatedTerminationPoints(modification);
+                    break;
+                case DELETE:
+                    processRemovedTerminationPoints(modification);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unhandled modification type: {}" +
+                            modification.getRootNode().getModificationType());
+            }
+        }
     }
 
-    /**
-     * @param removedPaths
-     */
-    private void processRemovedTerminationPoints(final Set<InstanceIdentifier<?>> removedNodes) {
-        for (final InstanceIdentifier<?> removedNode : removedNodes) {
-            final TpId terminationPointId = provideTopologyTerminationPointId(removedNode);
-            final InstanceIdentifier<TerminationPoint> iiToTopologyTerminationPoint = provideIIToTopologyTerminationPoint(
-                    terminationPointId, removedNode);
-
-            if (iiToTopologyTerminationPoint != null) {
-                final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> node = iiToTopologyTerminationPoint.firstIdentifierOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node.class);
-                operationProcessor.enqueueOperation(new TopologyOperation() {
-
-                    @Override
-                    public void applyOperation(final ReadWriteTransaction transaction) {
-                        Optional<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> nodeOptional = Optional.absent();
-                        try {
-                            nodeOptional = transaction.read(LogicalDatastoreType.OPERATIONAL, node).checkedGet();
-                        } catch (ReadFailedException e) {
-                            LOG.warn("Error occured when trying to read NodeConnector: {}", e.getMessage());
-                            LOG.debug("Error occured when trying to read NodeConnector.. ", e);
-                        }
-                        if (nodeOptional.isPresent()) {
-                            TopologyManagerUtil.removeAffectedLinks(terminationPointId, transaction, II_TO_TOPOLOGY);
-                            transaction.delete(LogicalDatastoreType.OPERATIONAL, iiToTopologyTerminationPoint);
-                        }
+    private void processRemovedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
+        final InstanceIdentifier<FlowCapableNodeConnector> removedNode = modification.getRootPath().getRootIdentifier();
+        final TpId terminationPointId = provideTopologyTerminationPointId(removedNode);
+        final InstanceIdentifier<TerminationPoint> iiToTopologyTerminationPoint = provideIIToTopologyTerminationPoint(
+                terminationPointId, removedNode);
+
+        if (iiToTopologyTerminationPoint != null) {
+            final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> node = iiToTopologyTerminationPoint.firstIdentifierOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node.class);
+            operationProcessor.enqueueOperation(new TopologyOperation() {
+                @Override
+                public void applyOperation(final ReadWriteTransaction transaction) {
+                    Optional<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> nodeOptional = Optional.absent();
+                    try {
+                        nodeOptional = transaction.read(LogicalDatastoreType.OPERATIONAL, node).checkedGet();
+                    } catch (ReadFailedException e) {
+                        LOG.warn("Error occured when trying to read NodeConnector: {}", e.getMessage());
+                        LOG.debug("Error occured when trying to read NodeConnector.. ", e);
                     }
-                });
-
-            } else {
-                LOG.debug("Instance identifier to inventory wasn't translated to topology while deleting termination point.");
-            }
+                    if (nodeOptional.isPresent()) {
+                        TopologyManagerUtil.removeAffectedLinks(terminationPointId, transaction, II_TO_TOPOLOGY);
+                        transaction.delete(LogicalDatastoreType.OPERATIONAL, iiToTopologyTerminationPoint);
+                    }
+                }
+            });
+        } else {
+            LOG.debug("Instance identifier to inventory wasn't translated to topology while deleting termination point.");
         }
     }
 
-    /**
-     * @param updatedData
-     */
-    private void processUpdatedTerminationPoints(final Map<InstanceIdentifier<?>, DataObject> updatedData) {
+    private void processUpdatedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
         // TODO Auto-generated method stub
     }
 
-    private void processAddedTerminationPoints(final Map<InstanceIdentifier<?>, DataObject> addedDatas) {
-        for (Entry<InstanceIdentifier<?>, DataObject> addedData : addedDatas.entrySet()) {
-            createData(addedData.getKey(), addedData.getValue());
-        }
-    }
-
-    protected void createData(final InstanceIdentifier<?> iiToNodeInInventory, final DataObject data) {
+    private void processAddedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
+        final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory = modification.getRootPath().getRootIdentifier();
         TpId terminationPointIdInTopology = provideTopologyTerminationPointId(iiToNodeInInventory);
         if (terminationPointIdInTopology != null) {
             InstanceIdentifier<TerminationPoint> iiToTopologyTerminationPoint = provideIIToTopologyTerminationPoint(
                     terminationPointIdInTopology, iiToNodeInInventory);
             TerminationPoint point = prepareTopologyTerminationPoint(terminationPointIdInTopology, iiToNodeInInventory);
             sendToTransactionChain(point, iiToTopologyTerminationPoint);
-            if (data instanceof FlowCapableNodeConnector) {
-                removeLinks((FlowCapableNodeConnector) data, point);
-            }
-
+            removeLinks(modification.getRootNode().getDataAfter(), point);
         } else {
             LOG.debug("Inventory node connector key is null. Data can't be written to topology termination point");
         }
     }
 
-    /**
-     * @param data
-     */
     private void removeLinks(final FlowCapableNodeConnector flowCapNodeConnector, final TerminationPoint point) {
         operationProcessor.enqueueOperation(new TopologyOperation() {
-
             @Override
             public void applyOperation(final ReadWriteTransaction transaction) {
                 if ((flowCapNodeConnector.getState() != null && flowCapNodeConnector.getState().isLinkDown())
@@ -131,23 +121,17 @@ public class TerminationPointChangeListenerImpl extends DataChangeListenerImpl {
     }
 
     private static TerminationPoint prepareTopologyTerminationPoint(final TpId terminationPointIdInTopology,
-            final InstanceIdentifier<?> iiToNodeInInventory) {
+                                                                    final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory) {
         final InventoryNodeConnector inventoryNodeConnector = new InventoryNodeConnectorBuilder()
-                .setInventoryNodeConnectorRef(
-                        new NodeConnectorRef(iiToNodeInInventory.firstIdentifierOf(NodeConnector.class))).build();
-
+                .setInventoryNodeConnectorRef(new NodeConnectorRef(iiToNodeInInventory.firstIdentifierOf(NodeConnector.class))).build();
         final TerminationPointBuilder terminationPointBuilder = new TerminationPointBuilder();
         terminationPointBuilder.setTpId(terminationPointIdInTopology);
         terminationPointBuilder.addAugmentation(InventoryNodeConnector.class, inventoryNodeConnector);
         return terminationPointBuilder.build();
     }
 
-    /**
-     * @param terminationPointIdInTopology
-     * @return
-     */
     private InstanceIdentifier<TerminationPoint> provideIIToTopologyTerminationPoint(final TpId terminationPointIdInTopology,
-            final InstanceIdentifier<?> iiToNodeInInventory) {
+                                                                                     final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory) {
         NodeId nodeIdInTopology = provideTopologyNodeId(iiToNodeInInventory);
         if (terminationPointIdInTopology != null && nodeIdInTopology != null) {
             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> iiToTopologyNode = provideIIToTopologyNode(nodeIdInTopology);
@@ -158,11 +142,7 @@ public class TerminationPointChangeListenerImpl extends DataChangeListenerImpl {
         }
     }
 
-    /**
-     * @param iiToNodeInInventory
-     * @return
-     */
-    private static TpId provideTopologyTerminationPointId(final InstanceIdentifier<?> iiToNodeInInventory) {
+    private static TpId provideTopologyTerminationPointId(final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory) {
         NodeConnectorKey inventoryNodeConnectorKey = iiToNodeInInventory.firstKeyOf(NodeConnector.class,
                 NodeConnectorKey.class);
         if (inventoryNodeConnectorKey != null) {
index 0f8a35e89ffe0032742c9bcd4a46a28efe046f0b..b3b7765e24c3ded5d846a05ec6d1d8818df19eac 100644 (file)
@@ -9,10 +9,9 @@ package org.opendaylight.openflowplugin.applications.topology.manager;
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import org.junit.After;
@@ -21,7 +20,11 @@ import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+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.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
@@ -34,10 +37,6 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-/**
- * @author joe
- *
- */
 public abstract class DataChangeListenerBase {
 
     @Mock
@@ -46,9 +45,6 @@ public abstract class DataChangeListenerBase {
     @Mock
     protected BindingTransactionChain mockTxChain;
 
-    @Mock
-    protected AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> mockedDataChangeListener;
-
     private OperationProcessor processor;
 
     protected InstanceIdentifier<Topology> topologyIID;
@@ -81,16 +77,22 @@ public abstract class DataChangeListenerBase {
         executor.shutdownNow();
     }
 
-    protected void mockDataChangeListener(Map<InstanceIdentifier<?>,DataObject> createdData, Map<InstanceIdentifier<?>, DataObject> updatedData, Set<?> removedPaths) {
-        doReturn(createdData == null ? Collections.emptyMap() : createdData).when(mockedDataChangeListener).getCreatedData();
-        doReturn(updatedData == null ? Collections.emptyMap() : updatedData).when(mockedDataChangeListener).getUpdatedData();
-        doReturn(removedPaths == null ? Collections.emptySet() : removedPaths).when(mockedDataChangeListener).getRemovedPaths();
-    }
-
     protected FlowCapableNodeConnector provideFlowCapableNodeConnector(final boolean isLinkDown, final boolean isPortDown) {
         FlowCapableNodeConnectorBuilder builder = new FlowCapableNodeConnectorBuilder();
         builder.setState(new StateBuilder().setLinkDown(isLinkDown).build());
         builder.setConfiguration(new PortConfig(true, true, true, isPortDown));
         return builder.build();
     }
+
+    protected <T extends DataObject> DataTreeModification setupDataTreeChange(final ModificationType type,
+                                                                              final InstanceIdentifier<T> ii) {
+        final DataTreeModification dataTreeModification = mock(DataTreeModification.class);
+        final DataTreeIdentifier identifier = new DataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, ii);
+        when(dataTreeModification.getRootNode()).thenReturn(mock(DataObjectModification.class));
+        when(dataTreeModification.getRootNode().getModificationType()).thenReturn(type);
+        when(dataTreeModification.getRootPath()).thenReturn(identifier);
+        when(dataTreeModification.getRootNode().getDataAfter()).thenReturn(mock(FlowCapableNodeConnector.class));
+        return dataTreeModification;
+    }
+
 }
index bb24ce44353f80a5fc1897fad72b22675a3797e0..676844a6bb4228de7d43ebb4189f09f6ae4f7133 100644 (file)
@@ -13,6 +13,8 @@ import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType.DELETE;
+import static org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType.WRITE;
 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.assertDeletedIDs;
 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newDestNode;
 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newInvNodeKey;
@@ -34,6 +36,7 @@ import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
@@ -47,13 +50,8 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 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.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-/**
- * @author joe
- *
- */
 public class NodeChangeListenerImplTest extends DataChangeListenerBase {
     @SuppressWarnings({ "rawtypes" })
     @Test
@@ -102,8 +100,8 @@ public class NodeChangeListenerImplTest extends DataChangeListenerBase {
 
         doReturn(mockTx1).when(mockTxChain).newReadWriteTransaction();
 
-        mockDataChangeListener(null, null, Collections.singleton(invNodeID));
-        nodeChangeListener.onDataChanged(mockedDataChangeListener);
+        DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeID);
+        nodeChangeListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
 
         waitForSubmit(submitLatch1);
 
@@ -151,8 +149,8 @@ public class NodeChangeListenerImplTest extends DataChangeListenerBase {
 
         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
 
-        mockDataChangeListener(null,null,Collections.singleton(invNodeID));
-        nodeChangeListener.onDataChanged(mockedDataChangeListener);
+        DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeID);
+        nodeChangeListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
 
         waitForSubmit(submitLatch);
 
@@ -174,9 +172,8 @@ public class NodeChangeListenerImplTest extends DataChangeListenerBase {
         CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
 
-        mockDataChangeListener(Collections.<InstanceIdentifier<?>, DataObject> singletonMap(
-                invNodeID, null), null, null);
-        nodeChangeListener.onDataChanged(mockedDataChangeListener);
+        DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeID);
+        nodeChangeListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
 
         waitForSubmit(submitLatch);
 
index f495b840dd2606e59f430e4e7f2a6eb120e84034..40f90c51dedcde22a6e0345c1c0bac2b075515db 100644 (file)
@@ -14,6 +14,9 @@ import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType.DELETE;
+import static org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType.WRITE;
 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.assertDeletedIDs;
 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newDestTp;
 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newInvNodeConnKey;
@@ -37,6 +40,7 @@ import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
@@ -52,13 +56,8 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-/**
- * @author joe
- *
- */
 public class TerminationPointChangeListenerImplTest extends DataChangeListenerBase{
     @SuppressWarnings("rawtypes")
     @Test
@@ -112,8 +111,8 @@ public class TerminationPointChangeListenerImplTest extends DataChangeListenerBa
 
         doReturn(mockTx1).when(mockTxChain).newReadWriteTransaction();
 
-        mockDataChangeListener(null, null, Collections.singleton(invNodeConnID));
-        terminationPointListener.onDataChanged(mockedDataChangeListener);
+        DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeConnID);
+        terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
 
         waitForSubmit(submitLatch1);
 
@@ -166,8 +165,8 @@ public class TerminationPointChangeListenerImplTest extends DataChangeListenerBa
 
         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
 
-        mockDataChangeListener(null, null, Collections.singleton(invNodeConnID));
-        terminationPointListener.onDataChanged(mockedDataChangeListener);
+        DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeConnID);
+        terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
 
         waitForSubmit(submitLatch);
 
@@ -191,9 +190,8 @@ public class TerminationPointChangeListenerImplTest extends DataChangeListenerBa
         CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
 
-        mockDataChangeListener(Collections.<InstanceIdentifier<?>, DataObject> singletonMap(
-                invNodeConnID, null), null, null);
-        terminationPointListener.onDataChanged(mockedDataChangeListener);
+        DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
+        terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
 
         waitForSubmit(submitLatch);
 
@@ -240,9 +238,9 @@ public class TerminationPointChangeListenerImplTest extends DataChangeListenerBa
 
         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
 
-        mockDataChangeListener(Collections.<InstanceIdentifier<?>, DataObject> singletonMap(
-                invNodeConnID, provideFlowCapableNodeConnector(true, false)), null, null);
-        terminationPointListener.onDataChanged(mockedDataChangeListener);
+        DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
+        when(dataTreeModification.getRootNode().getDataAfter()).thenReturn(provideFlowCapableNodeConnector(true, false));
+        terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
 
         waitForDeletes(1, deleteLatch);
 
@@ -285,9 +283,9 @@ public class TerminationPointChangeListenerImplTest extends DataChangeListenerBa
 
         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
 
-        mockDataChangeListener(Collections.<InstanceIdentifier<?>, DataObject> singletonMap(
-                invNodeConnID, provideFlowCapableNodeConnector(false, true)), null, null);
-        terminationPointListener.onDataChanged(mockedDataChangeListener);
+        DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
+        when(dataTreeModification.getRootNode().getDataAfter()).thenReturn(provideFlowCapableNodeConnector(false, true));
+        terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
 
         waitForDeletes(1, deleteLatch);
 
index da5f80e1137feb6d55e54b4763496dfb15a988d7..06081fdbb60c3fed4ebf66f6316b9fd2d21b9c89 100644 (file)
@@ -66,28 +66,24 @@ public class TestUtils {
         }
     }
 
-    static void setReadFutureAsync(final Topology topology,
-            final SettableFuture<Optional<Topology>> readFuture) {
+    static void setReadFutureAsync(final Topology topology, final SettableFuture<Optional<Topology>> readFuture) {
         new Thread() {
             @Override
             public void run() {
-                Uninterruptibles.sleepUninterruptibly(50, TimeUnit.MILLISECONDS);
+                Uninterruptibles.sleepUninterruptibly(5, TimeUnit.SECONDS);
                 readFuture.set(Optional.of(topology));
             }
-
         }.start();
     }
 
     static void waitForSubmit(CountDownLatch latch) {
-        assertEquals("Transaction submitted", true,
-                Uninterruptibles.awaitUninterruptibly(latch, 5, TimeUnit.SECONDS));
+        assertEquals("Transaction submitted", true, Uninterruptibles.awaitUninterruptibly(latch, 5, TimeUnit.SECONDS));
     }
 
     static void waitForDeletes(int expDeleteCalls, final CountDownLatch latch) {
         boolean done = Uninterruptibles.awaitUninterruptibly(latch, 5, TimeUnit.SECONDS);
         if(!done) {
-            fail("Expected " + expDeleteCalls + " delete calls. Actual: " +
-                    (expDeleteCalls - latch.getCount()));
+            fail("Expected " + expDeleteCalls + " delete calls. Actual: " + (expDeleteCalls - latch.getCount()));
         }
     }
 
@@ -95,8 +91,7 @@ public class TestUtils {
         final CountDownLatch latch = new CountDownLatch(1);
         doAnswer(new Answer<CheckedFuture<Void, TransactionCommitFailedException>>() {
             @Override
-            public CheckedFuture<Void, TransactionCommitFailedException> answer(
-                                                            InvocationOnMock invocation) {
+            public CheckedFuture<Void, TransactionCommitFailedException> answer(InvocationOnMock invocation) {
                 latch.countDown();
                 return Futures.immediateCheckedFuture(null);
             }
@@ -106,8 +101,8 @@ public class TestUtils {
     }
 
     @SuppressWarnings("rawtypes")
-    static void setupStubbedDeletes(ReadWriteTransaction mockTx,
-            ArgumentCaptor<InstanceIdentifier> deletedLinkIDs, final CountDownLatch latch) {
+    static void setupStubbedDeletes(ReadWriteTransaction mockTx, ArgumentCaptor<InstanceIdentifier> deletedLinkIDs,
+                                    final CountDownLatch latch) {
         doAnswer(new Answer<Void>() {
             @Override
             public Void answer(InvocationOnMock invocation) {
diff --git a/applications/topology-manager/src/test/resources/log4j.xml b/applications/topology-manager/src/test/resources/log4j.xml
new file mode 100644 (file)
index 0000000..48660d6
--- /dev/null
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+  -->
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+    <appender name="console" class="org.apache.log4j.ConsoleAppender">
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="%-6p %d{HH:mm:ss.SSS} [%10.10t] %30.30c %x - %m%n" />
+        </layout>
+        <!--         <param name="Threshold" value="DEBUG" /> -->
+    </appender>
+
+    <logger name="org.opendaylight.openflowplugin" additivity="false">
+        <level value="DEBUG" />
+        <appender-ref ref="console" />
+    </logger>
+
+    <logger name="org.opendaylight.openflowplugin.impl" additivity="false">
+        <level value="DEBUG" />
+        <appender-ref ref="console" />
+    </logger>
+
+    <logger name="org.opendaylight.openflowplugin.impl.connection" additivity="false">
+        <level value="TRACE" />
+        <appender-ref ref="console" />
+    </logger>
+
+    <logger name="org.opendaylight.openflowplugin.impl.device" additivity="false">
+        <level value="TRACE" />
+        <appender-ref ref="console" />
+    </logger>
+
+    <logger name="org.opendaylight.openflowplugin.openflow.md.core.HandshakeManagerImpl" additivity="false">
+        <level value="TRACE" />
+        <appender-ref ref="console" />
+    </logger>
+
+    <root>
+        <priority value="INFO" />
+        <appender-ref ref="console" />
+    </root>
+</log4j:configuration>