Convert DataChangeListeners to DataTreeChangeListeners
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / node / FlowCapableNodeConnectorListener.java
index f74dabf5ede8758b09838f9c74528ea39503830c..5e538ab5bff0aba9394ef64475e071889d3aff79 100644 (file)
@@ -1,26 +1,40 @@
+/*
+ * Copyright (c) 2014 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
+ */
+
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Map.Entry;
-
 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.DataObjectModification;
+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.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-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.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3ContextBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
@@ -29,16 +43,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.No
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.Futures;
-
-public class FlowCapableNodeConnectorListener implements DataChangeListener, AutoCloseable {
+public class FlowCapableNodeConnectorListener implements DataTreeChangeListener<FlowCapableNodeConnector>,
+        AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(FlowCapableNodeConnectorListener.class);
 
@@ -52,80 +62,78 @@ public class FlowCapableNodeConnectorListener implements DataChangeListener, Aut
         .build();
     private final DataBroker dataProvider;
     private final SwitchManager switchManager;
-    private final ListenerRegistration<DataChangeListener> listenerRegistration;
+    private final ListenerRegistration<?> listenerRegistration;
 
     public FlowCapableNodeConnectorListener(DataBroker dataProvider, SwitchManager switchManager) {
         this.dataProvider = checkNotNull(dataProvider);
         this.switchManager = checkNotNull(switchManager);
-        listenerRegistration = dataProvider.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                fcNodeConnectorIid, this, DataChangeScope.BASE);
+        listenerRegistration = dataProvider.registerDataTreeChangeListener(new DataTreeIdentifier<>(
+                LogicalDatastoreType.OPERATIONAL, fcNodeConnectorIid), this);
     }
 
     @Override
-    public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+    public void onDataTreeChanged(Collection<DataTreeModification<FlowCapableNodeConnector>> changes) {
         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+
+        //endpoint and endpoint L3 maps
         Map<Name, Endpoint> epWithOfOverlayAugByPortName = readEpsWithOfOverlayAugByPortName(rwTx);
+        Map<Name, EndpointL3> l3EpWithOfOverlayAugByPortName = readL3EpsWithOfOverlayAugByPortName(rwTx);
+
         boolean isDataPutToTx = false;
-        for (Entry<InstanceIdentifier<?>, DataObject> fcncEntry : change.getCreatedData().entrySet()) {
-            if (FlowCapableNodeConnector.class.equals(fcncEntry.getKey().getTargetType())) {
-                InstanceIdentifier<NodeConnector> ncIid = fcncEntry.getKey().firstIdentifierOf(NodeConnector.class);
-                FlowCapableNodeConnector fcnc = (FlowCapableNodeConnector) fcncEntry.getValue();
-                LOG.trace(
-                        "FlowCapableNodeConnector created: NodeId: {} NodeConnectorId: {} FlowCapableNodeConnector: {}",
-                        ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
-                        ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue(), fcnc);
-                switchManager.updateSwitchNodeConnectorConfig(ncIid, fcnc);
-                Name portName = getPortName(fcnc);
-                boolean updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
-                if (updated == true) {
-                    isDataPutToTx = true;
-                }
-            }
-        }
-        for (Entry<InstanceIdentifier<?>, DataObject> fcncEntry : change.getUpdatedData().entrySet()) {
-            if (FlowCapableNodeConnector.class.equals(fcncEntry.getKey().getTargetType())) {
-                InstanceIdentifier<NodeConnector> ncIid = fcncEntry.getKey().firstIdentifierOf(NodeConnector.class);
-                FlowCapableNodeConnector fcnc = (FlowCapableNodeConnector) fcncEntry.getValue();
-                LOG.trace(
-                        "FlowCapableNodeConnector updated: NodeId: {} NodeConnectorId: {} FlowCapableNodeConnector: {}",
-                        ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
-                        ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue(), fcnc);
-                switchManager.updateSwitchNodeConnectorConfig(ncIid, fcnc);
-                Name portName = getPortName(fcnc);
-                boolean updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
-                if (updated == true) {
-                    isDataPutToTx = true;
-                }
-                FlowCapableNodeConnector originalFcnc = (FlowCapableNodeConnector) change.getOriginalData().get(
-                        fcncEntry.getKey());
-                Name portNameFromOriginalFcnc = getPortName(originalFcnc);
-                // portname already existed and then was changed
-                if (portNameFromOriginalFcnc != null && !Objects.equal(portNameFromOriginalFcnc, portName)) {
-                    updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portNameFromOriginalFcnc),
-                            null, rwTx);
-                    if (updated == true) {
+        for (DataTreeModification<FlowCapableNodeConnector> change: changes) {
+            DataObjectModification<FlowCapableNodeConnector> rootNode = change.getRootNode();
+            InstanceIdentifier<NodeConnector> ncIid = change.getRootPath().getRootIdentifier()
+                    .firstIdentifierOf(NodeConnector.class);
+            final FlowCapableNodeConnector originalFcnc = rootNode.getDataBefore();
+            boolean updated;
+            boolean l3Updated;
+            switch (rootNode.getModificationType()) {
+                case SUBTREE_MODIFIED:
+                case WRITE:
+                    FlowCapableNodeConnector fcnc = rootNode.getDataAfter();
+                    LOG.trace(
+                            "FlowCapableNodeConnector updated: NodeId: {} NodeConnectorId: {} FlowCapableNodeConnector: {}",
+                            ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
+                            ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue(), fcnc);
+                    switchManager.updateSwitchNodeConnectorConfig(ncIid, fcnc);
+                    Name portName = getPortName(fcnc);
+                    updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
+                    l3Updated = updateL3EpWithNodeConnectorInfo(l3EpWithOfOverlayAugByPortName.get(portName), ncIid, rwTx);
+                    if (updated || l3Updated) {
                         isDataPutToTx = true;
                     }
-                }
-            }
-        }
-        for (InstanceIdentifier<?> fcncIid : change.getRemovedPaths()) {
-            if (FlowCapableNodeConnector.class.equals(fcncIid.getTargetType())) {
-                InstanceIdentifier<NodeConnector> ncIid = fcncIid.firstIdentifierOf(NodeConnector.class);
-                FlowCapableNodeConnector originalFcnc = (FlowCapableNodeConnector) change.getOriginalData()
-                    .get(fcncIid);
-                LOG.trace("FlowCapableNodeConnector removed: NodeId: {} NodeConnectorId: {}",
-                        ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
-                        ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue());
-                switchManager.updateSwitchNodeConnectorConfig(ncIid, null);
-                Name portNameFromOriginalFcnc = getPortName(originalFcnc);
-                boolean updated = updateEpWithNodeConnectorInfo(
-                        epWithOfOverlayAugByPortName.get(portNameFromOriginalFcnc), null, rwTx);
-                if (updated == true) {
-                    isDataPutToTx = true;
-                }
+
+                    if (originalFcnc != null) {
+                        Name portNameFromOriginalFcnc = getPortName(originalFcnc);
+                        // port name already existed and then was changed
+                        if (portNameFromOriginalFcnc != null && !Objects.equal(portNameFromOriginalFcnc, portName)) {
+                            updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName
+                                    .get(portNameFromOriginalFcnc), null, rwTx);
+                            l3Updated = updateL3EpWithNodeConnectorInfo(l3EpWithOfOverlayAugByPortName
+                                    .get(portNameFromOriginalFcnc), null, rwTx);
+                            if (updated || l3Updated) {
+                                isDataPutToTx = true;
+                            }
+                        }
+                    }
+                    break;
+                case DELETE:
+                    LOG.trace("FlowCapableNodeConnector removed: NodeId: {} NodeConnectorId: {}",
+                            ncIid.firstKeyOf(Node.class, NodeKey.class).getId().getValue(),
+                            ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId().getValue());
+                    switchManager.updateSwitchNodeConnectorConfig(ncIid, null);
+                    Name portNameFromOriginalFcnc = getPortName(originalFcnc);
+                    updated = updateEpWithNodeConnectorInfo(epWithOfOverlayAugByPortName.get(portNameFromOriginalFcnc), null, rwTx);
+                    l3Updated = updateL3EpWithNodeConnectorInfo(l3EpWithOfOverlayAugByPortName.get(portNameFromOriginalFcnc), null, rwTx);
+                    if (updated || l3Updated) {
+                        isDataPutToTx = true;
+                    }
+                    break;
+                default:
+                    break;
             }
         }
+
         if (isDataPutToTx) {
             rwTx.submit();
         } else {
@@ -133,6 +141,7 @@ public class FlowCapableNodeConnectorListener implements DataChangeListener, Aut
         }
     }
 
+    //read endpoints from listener entry
     private Map<Name, Endpoint> readEpsWithOfOverlayAugByPortName(ReadTransaction rTx) {
         Optional<Endpoints> potentialEps = Futures.getUnchecked(rTx.read(LogicalDatastoreType.OPERATIONAL, endpointsIid));
         if (!potentialEps.isPresent() || potentialEps.get().getEndpoint() == null) {
@@ -148,6 +157,22 @@ public class FlowCapableNodeConnectorListener implements DataChangeListener, Aut
         return epsByPortName;
     }
 
+    //read l3 endpoint from listener entry
+    private Map<Name, EndpointL3> readL3EpsWithOfOverlayAugByPortName(ReadTransaction rTx) {
+        Optional<Endpoints> potentialEps = Futures.getUnchecked(rTx.read(LogicalDatastoreType.OPERATIONAL, endpointsIid));
+        if (!potentialEps.isPresent() || potentialEps.get().getEndpoint() == null) {
+            return Collections.emptyMap();
+        }
+        Map<Name, EndpointL3> epsByPortName = new HashMap<>();
+        for (EndpointL3 epL3 : potentialEps.get().getEndpointL3()) {
+            OfOverlayL3Context ofOverlayL3Ep = epL3.getAugmentation(OfOverlayL3Context.class);
+            if (ofOverlayL3Ep != null && ofOverlayL3Ep.getPortName() != null) {
+                epsByPortName.put(ofOverlayL3Ep.getPortName(), epL3);
+            }
+        }
+        return epsByPortName;
+    }
+
     private Name getPortName(FlowCapableNodeConnector fcnc) {
         if (fcnc == null || fcnc.getName() == null) {
             return null;
@@ -156,7 +181,7 @@ public class FlowCapableNodeConnectorListener implements DataChangeListener, Aut
     }
 
     /**
-     * @return {@code true} if data was put to the transaction; {@code false} otherwise
+     * @return {@code true} if data (Endpoint) was put to the transaction; {@code false} otherwise
      */
     private boolean updateEpWithNodeConnectorInfo(Endpoint epWithOfOverlayAug, InstanceIdentifier<NodeConnector> ncIid,
             WriteTransaction tx) {
@@ -176,6 +201,10 @@ public class FlowCapableNodeConnectorListener implements DataChangeListener, Aut
             NodeId nodeId = ncIid.firstKeyOf(Node.class, NodeKey.class).getId();
             newOfOverlayAug.setNodeId(nodeId);
             newOfOverlayAug.setNodeConnectorId(ncId);
+        } else {
+            //when nodeId is null, remove info about that node from endpoint
+            newOfOverlayAug.setNodeId(null);
+            newOfOverlayAug.setNodeConnectorId(null);
         }
         InstanceIdentifier<OfOverlayContext> epOfOverlayAugIid = InstanceIdentifier.builder(Endpoints.class)
             .child(Endpoint.class, epWithOfOverlayAug.getKey())
@@ -185,11 +214,44 @@ public class FlowCapableNodeConnectorListener implements DataChangeListener, Aut
         return true;
     }
 
+    /**
+     * @return {@code true} if data (EndpointL3) was put to the transaction; {@code false} otherwise
+     */
+    private boolean updateL3EpWithNodeConnectorInfo(EndpointL3 epWithOfOverlayL3Aug,
+            InstanceIdentifier<NodeConnector> ncIid, WriteTransaction tx) {
+        if (epWithOfOverlayL3Aug == null) {
+            return false;
+        }
+        OfOverlayL3Context oldOfOverlayL3Aug = epWithOfOverlayL3Aug.getAugmentation(OfOverlayL3Context.class);
+        OfOverlayL3ContextBuilder newOfOverlayL3Aug = new OfOverlayL3ContextBuilder(oldOfOverlayL3Aug);
+        if (ncIid == null && oldOfOverlayL3Aug.getNodeConnectorId() == null) {
+            return false;
+        }
+        if (ncIid != null) {
+            NodeConnectorId ncId = ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
+            if (ncId.equals(oldOfOverlayL3Aug.getNodeConnectorId())) {
+                return false;
+            }
+            NodeId nodeId = ncIid.firstKeyOf(Node.class, NodeKey.class).getId();
+            newOfOverlayL3Aug.setNodeId(nodeId);
+            newOfOverlayL3Aug.setNodeConnectorId(ncId);
+        } else {
+            // remove node info
+            newOfOverlayL3Aug.setNodeId(null);
+            newOfOverlayL3Aug.setNodeConnectorId(null);
+        }
+        InstanceIdentifier<OfOverlayL3Context> epOfOverlayAugIid = InstanceIdentifier.builder(Endpoints.class)
+                .child(EndpointL3.class, epWithOfOverlayL3Aug.getKey())
+                .augmentation(OfOverlayL3Context.class)
+                .build();
+        tx.put(LogicalDatastoreType.OPERATIONAL, epOfOverlayAugIid, newOfOverlayL3Aug.build());
+        return true;
+    }
+
     @Override
     public void close() throws Exception {
         if (listenerRegistration != null) {
             listenerRegistration.close();
         }
     }
-
 }