Topology Manager to skip redundant edge updates
[controller.git] / opendaylight / topologymanager / implementation / src / main / java / org / opendaylight / controller / topologymanager / internal / TopologyManagerImpl.java
index 004d1b98db3eff61292937888a6fa34b1f9a4ee6..526ba41c354c3166db9ba26f18e55b1483c1ab36 100644 (file)
@@ -53,6 +53,7 @@ import org.opendaylight.controller.sal.utils.ObjectReader;
 import org.opendaylight.controller.sal.utils.ObjectWriter;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.opendaylight.controller.topologymanager.ITopologyManager;
 import org.opendaylight.controller.topologymanager.ITopologyManagerAware;
 import org.opendaylight.controller.topologymanager.ITopologyManagerClusterWideAware;
@@ -68,7 +69,7 @@ import org.slf4j.LoggerFactory;
  * topology database and notifies all the listeners of topology changes.
  */
 public class TopologyManagerImpl implements
-        ICacheUpdateAware,
+        ICacheUpdateAware<Object, Object>,
         ITopologyManager,
         IConfigurationContainerAware,
         IListenTopoUpdates,
@@ -79,9 +80,9 @@ public class TopologyManagerImpl implements
     static final String TOPONODECONNECTORDB = "topologymanager.nodeConnectorDB";
     static final String TOPOUSERLINKSDB = "topologymanager.userLinksDB";
     private static final Logger log = LoggerFactory.getLogger(TopologyManagerImpl.class);
-    private static final String SAVE = "Save";
     private ITopologyService topoService;
     private IClusterContainerServices clusterContainerService;
+    private ISwitchManager switchManager;
     // DB of all the Edges with properties which constitute our topology
     private ConcurrentMap<Edge, Set<Property>> edgesDB;
     // DB of all NodeConnector which are part of ISL Edges, meaning they
@@ -162,6 +163,18 @@ public class TopologyManagerImpl implements
         }
     }
 
+    void setSwitchManager(ISwitchManager s) {
+        log.debug("Adding ISwitchManager: {}", s);
+        this.switchManager = s;
+    }
+
+    void unsetSwitchManager(ISwitchManager s) {
+        if (this.switchManager == s) {
+            log.debug("Removing ISwitchManager: {}", s);
+            this.switchManager = null;
+        }
+    }
+
     /**
      * Function called by the dependency manager when all the required
      * dependencies are satisfied
@@ -187,7 +200,7 @@ public class TopologyManagerImpl implements
         notifyThread = new Thread(new TopologyNotify(notifyQ));
     }
 
-    @SuppressWarnings({ "unchecked", "deprecation" })
+    @SuppressWarnings({ "unchecked" })
     private void allocateCaches() {
         try {
             this.edgesDB =
@@ -230,7 +243,7 @@ public class TopologyManagerImpl implements
         }
     }
 
-    @SuppressWarnings({ "unchecked", "deprecation" })
+    @SuppressWarnings({ "unchecked" })
     private void retrieveCaches() {
         if (this.clusterContainerService == null) {
             log.error("Cluster Services is null, can't retrieve caches.");
@@ -508,9 +521,27 @@ public class TopologyManagerImpl implements
         }
     }
 
+    private boolean nodeConnectorsExist(Edge e) {
+        NodeConnector head = e.getHeadNodeConnector();
+        NodeConnector tail = e.getTailNodeConnector();
+        return (switchManager.doesNodeConnectorExist(head) &&
+                switchManager.doesNodeConnectorExist(tail));
+    }
+
     private TopoEdgeUpdate edgeUpdate(Edge e, UpdateType type, Set<Property> props) {
         switch (type) {
         case ADDED:
+            // Avoid redundant update as notifications trigger expensive tasks
+            if (edgesDB.containsKey(e)) {
+                log.trace("Skipping redundant edge addition: {}", e);
+                return null;
+            }
+            // Ensure that both tail and head node connectors exist.
+            if (!nodeConnectorsExist(e)) {
+                log.warn("Ignore edge that contains invalid node connector: {}", e);
+                return null;
+            }
+
             // Make sure the props are non-null
             if (props == null) {
                 props = new HashSet<Property>();
@@ -632,18 +663,21 @@ public class TopologyManagerImpl implements
             Set<Property> p = topoedgeupdateList.get(i).getProperty();
             UpdateType type = topoedgeupdateList.get(i).getUpdateType();
             TopoEdgeUpdate teu = edgeUpdate(e, type, p);
-            teuList.add(teu);
+            if (teu != null) {
+                teuList.add(teu);
+            }
         }
 
-        // Now update the listeners
-        for (ITopologyManagerAware s : this.topologyManagerAware) {
-            try {
-                s.edgeUpdate(teuList);
-            } catch (Exception exc) {
-                log.error("Exception on edge update:", exc);
+        if (!teuList.isEmpty()) {
+            // Now update the listeners
+            for (ITopologyManagerAware s : this.topologyManagerAware) {
+                try {
+                    s.edgeUpdate(teuList);
+                } catch (Exception exc) {
+                    log.error("Exception on edge update:", exc);
+                }
             }
         }
-
     }
 
     private Edge getReverseLinkTuple(TopologyUserLinkConfig link) {
@@ -693,7 +727,14 @@ public class TopologyManagerImpl implements
         Edge linkTuple = getLinkTuple(userLink);
         if (linkTuple != null) {
             if (!isProductionLink(linkTuple)) {
-                edgeUpdate(linkTuple, UpdateType.ADDED, new HashSet<Property>());
+                TopoEdgeUpdate teu = edgeUpdate(linkTuple, UpdateType.ADDED,
+                                                new HashSet<Property>());
+                if (teu == null) {
+                    userLinksDB.remove(userLink.getName());
+                    return new Status(StatusCode.NOTFOUND,
+                           "Link configuration contains invalid node connector: "
+                           + userLink);
+                }
             }
 
             linkTuple = getReverseLinkTuple(userLink);
@@ -860,7 +901,7 @@ public class TopologyManagerImpl implements
     public void entryUpdated(final Object key, final Object new_value, final String cacheName, final boolean originLocal) {
         if (cacheName.equals(TOPOEDGESDB)) {
             final Edge e = (Edge) key;
-            log.trace("Edge {} CHANGED isLocal:{}", e, originLocal);
+            log.trace("Edge {} UPDATED isLocal:{}", e, originLocal);
             final Set<Property> props = (Set<Property>) new_value;
             edgeUpdateClusterWide(e, UpdateType.CHANGED, props, originLocal);
         }
@@ -918,10 +959,10 @@ public class TopologyManagerImpl implements
                     // Lets sleep for sometime to allow aggregation of event
                     Thread.sleep(100);
                 } catch (InterruptedException e1) {
-                    log.warn("TopologyNotify interrupted {}", e1.getMessage());
                     if (shuttingDown) {
                         return;
                     }
+                    log.warn("TopologyNotify interrupted {}", e1.getMessage());
                 } catch (Exception e2) {
                     log.error("", e2);
                 }