Merge "Fix for cache cleanup in protocol plugin on container deletion"
authorGiovanni Meo <gmeo@cisco.com>
Fri, 13 Sep 2013 15:24:27 +0000 (15:24 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 13 Sep 2013 15:24:27 +0000 (15:24 +0000)
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Activator.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DataPacketMuxDemux.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DiscoveryService.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/ReadServiceFilter.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServiceShim.java

index 05736f779e6111f2a7619dc7734aeca0362717ef..ee62204f3fa233e4918ec3f3aaa3470e051755b3 100644 (file)
@@ -31,6 +31,7 @@ import org.opendaylight.controller.protocol_plugin.openflow.core.internal.Contro
 import org.opendaylight.controller.sal.connection.IPluginInConnectionService;
 import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.opendaylight.controller.sal.core.IContainerAware;
 import org.opendaylight.controller.sal.core.IContainerListener;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
@@ -273,12 +274,9 @@ public class Activator extends ComponentActivatorAbstractBase {
             // by SAL
             props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
             c.setInterface(
-                    new String[] {
-                            IPluginInFlowProgrammerService.class.getName(),
-                            IMessageListener.class.getName(),
-                            IContainerListener.class.getName(),
-                            IInventoryShimExternalListener.class.getName() },
-                            props);
+                    new String[] { IPluginInFlowProgrammerService.class.getName(), IMessageListener.class.getName(),
+                            IContainerListener.class.getName(), IInventoryShimExternalListener.class.getName(),
+                            IContainerAware.class.getName() }, props);
 
             c.add(createServiceDependency()
                     .setService(IController.class, "(name=Controller)")
@@ -300,10 +298,8 @@ public class Activator extends ComponentActivatorAbstractBase {
 
         if (imp.equals(ReadServiceFilter.class)) {
 
-            c.setInterface(new String[] {
-                    IReadServiceFilter.class.getName(),
-                    IContainerListener.class.getName(),
-                    IOFStatisticsListener.class.getName() }, null);
+            c.setInterface(new String[] { IReadServiceFilter.class.getName(), IContainerListener.class.getName(),
+                    IOFStatisticsListener.class.getName(), IContainerAware.class.getName() }, null);
 
             c.add(createServiceDependency()
                     .setService(IController.class, "(name=Controller)")
@@ -338,9 +334,7 @@ public class Activator extends ComponentActivatorAbstractBase {
         if (imp.equals(DiscoveryService.class)) {
             // export the service
             c.setInterface(
-                    new String[] {
-                            IInventoryShimExternalListener.class.getName(),
-                            IDataPacketListen.class.getName(),
+                    new String[] { IInventoryShimExternalListener.class.getName(), IDataPacketListen.class.getName(),
                             IContainerListener.class.getName() }, null);
 
             c.add(createServiceDependency()
@@ -369,9 +363,8 @@ public class Activator extends ComponentActivatorAbstractBase {
         // DataPacket mux/demux services, which is teh actual engine
         // doing the packet switching
         if (imp.equals(DataPacketMuxDemux.class)) {
-            c.setInterface(new String[] { IDataPacketMux.class.getName(),
-                    IContainerListener.class.getName(),
-                    IInventoryShimExternalListener.class.getName() }, null);
+            c.setInterface(new String[] { IDataPacketMux.class.getName(), IContainerListener.class.getName(),
+                    IInventoryShimExternalListener.class.getName(), IContainerAware.class.getName() }, null);
 
             c.add(createServiceDependency()
                     .setService(IController.class, "(name=Controller)")
@@ -419,7 +412,7 @@ public class Activator extends ComponentActivatorAbstractBase {
 
         if (imp.equals(InventoryServiceShim.class)) {
             c.setInterface(new String[] { IContainerListener.class.getName(),
-                    IOFStatisticsListener.class.getName()}, null);
+                    IOFStatisticsListener.class.getName(), IContainerAware.class.getName() }, null);
 
             c.add(createServiceDependency()
                     .setService(IController.class, "(name=Controller)")
@@ -448,10 +441,9 @@ public class Activator extends ComponentActivatorAbstractBase {
         }
 
         if (imp.equals(TopologyServiceShim.class)) {
-            c.setInterface(new String[] { IDiscoveryListener.class.getName(),
-                    IContainerListener.class.getName(),
-                    IRefreshInternalProvider.class.getName(),
-                    IInventoryShimExternalListener.class.getName() }, null);
+            c.setInterface(new String[] { IDiscoveryListener.class.getName(), IContainerListener.class.getName(),
+                    IRefreshInternalProvider.class.getName(), IInventoryShimExternalListener.class.getName(),
+                    IContainerAware.class.getName() }, null);
           c.add(createServiceDependency()
                     .setService(ITopologyServiceShimListener.class)
                     .setCallbacks("setTopologyServiceShimListener",
index 7a01d3bd19bce2060a6749bb017e08026a84aaea..a1fcd1ab23b7c5a8836d5ad1200533b5a08a03ec 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.controller.protocol_plugin.openflow.internal;
 
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -22,19 +23,10 @@ import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimExtern
 import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
 import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListener;
 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
 import org.opendaylight.controller.sal.core.ConstructionException;
 import org.opendaylight.controller.sal.core.ContainerFlow;
+import org.opendaylight.controller.sal.core.IContainerAware;
 import org.opendaylight.controller.sal.core.IContainerListener;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
@@ -45,9 +37,18 @@ import org.opendaylight.controller.sal.packet.PacketResult;
 import org.opendaylight.controller.sal.packet.RawPacket;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.HexEncode;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPacketIn;
+import org.openflow.protocol.OFPacketOut;
+import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionOutput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class DataPacketMuxDemux implements IContainerListener,
-        IMessageListener, IDataPacketMux, IInventoryShimExternalListener {
+        IMessageListener, IDataPacketMux, IInventoryShimExternalListener, IContainerAware {
     protected static final Logger logger = LoggerFactory
             .getLogger(DataPacketMuxDemux.class);
     private IController controller = null;
@@ -375,14 +376,13 @@ public class DataPacketMuxDemux implements IContainerListener,
         }
         switch (t) {
         case ADDED:
-            if (!fSpecs.contains(previousFlow)) {
-                fSpecs.add(previousFlow);
+            if (!fSpecs.contains(currentFlow)) {
+                fSpecs.add(currentFlow);
             }
+            container2FlowSpecs.put(containerName, fSpecs);
             break;
         case REMOVED:
-            if (fSpecs.contains(previousFlow)) {
-                fSpecs.remove(previousFlow);
-            }
+            fSpecs.remove(currentFlow);
             break;
         case CHANGED:
             break;
@@ -452,4 +452,29 @@ public class DataPacketMuxDemux implements IContainerListener,
             UpdateType type, Set<Property> props) {
         // do nothing
     }
+
+    @Override
+    public void containerCreate(String containerName) {
+        // do nothing
+    }
+
+    @Override
+    public void containerDestroy(String containerName) {
+        Set<NodeConnector> removeNodeConnectorSet = new HashSet<NodeConnector>();
+        for (Map.Entry<NodeConnector, List<String>> entry : nc2Container.entrySet()) {
+            List<String> ncContainers = entry.getValue();
+            if (ncContainers.contains(containerName)) {
+                NodeConnector nodeConnector = entry.getKey();
+                removeNodeConnectorSet.add(nodeConnector);
+            }
+        }
+        for (NodeConnector nodeConnector : removeNodeConnectorSet) {
+            List<String> ncContainers = nc2Container.get(nodeConnector);
+            ncContainers.remove(containerName);
+            if (ncContainers.isEmpty()) {
+                nc2Container.remove(nodeConnector);
+            }
+        }
+        container2FlowSpecs.remove(containerName);
+    }
 }
index c55a88cd3f0224cc587bc01e632e742405cc34f1..88b75b196dcec8f370a6119130d21f3578aa89ab 100644 (file)
@@ -25,6 +25,7 @@ import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListene
 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
 import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
 import org.opendaylight.controller.sal.core.ContainerFlow;
+import org.opendaylight.controller.sal.core.IContainerAware;
 import org.opendaylight.controller.sal.core.IContainerListener;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.Node.NodeIDType;
@@ -58,7 +59,7 @@ import org.slf4j.LoggerFactory;
  */
 public class FlowProgrammerService implements IPluginInFlowProgrammerService,
         IMessageListener, IContainerListener, IInventoryShimExternalListener,
-        CommandProvider {
+        CommandProvider, IContainerAware {
     private static final Logger log = LoggerFactory
             .getLogger(FlowProgrammerService.class);
     private IController controller;
@@ -465,8 +466,6 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
     @Override
     public void nodeConnectorUpdated(String containerName, NodeConnector p,
             UpdateType type) {
-        Set<NodeConnector> target = null;
-
         switch (type) {
         case ADDED:
             if (!containerToNc.containsKey(containerName)) {
@@ -477,7 +476,7 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
         case CHANGED:
             break;
         case REMOVED:
-            target = containerToNc.get(containerName);
+            Set<NodeConnector> target = containerToNc.get(containerName);
             if (target != null) {
                 target.remove(p);
             }
@@ -800,4 +799,14 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
         ci.println("Max num of async messages sent prior to the Barrier message is "
                 + barrierMessagePriorCount);
     }
+
+    @Override
+    public void containerCreate(String containerName) {
+        // do nothing
+    }
+
+    @Override
+    public void containerDestroy(String containerName) {
+        containerToNc.remove(containerName);
+    }
 }
index 92eec43b4ce58487465ae243c46aa3c0f87b6027..8db83f0fc7e2449b99079aadf5dfc709204f2f35 100644 (file)
@@ -32,6 +32,7 @@ import org.opendaylight.controller.sal.core.Buffers;
 import org.opendaylight.controller.sal.core.Capabilities;
 import org.opendaylight.controller.sal.core.ContainerFlow;
 import org.opendaylight.controller.sal.core.Description;
+import org.opendaylight.controller.sal.core.IContainerAware;
 import org.opendaylight.controller.sal.core.IContainerListener;
 import org.opendaylight.controller.sal.core.MacAddress;
 import org.opendaylight.controller.sal.core.Node;
@@ -59,7 +60,7 @@ import org.slf4j.LoggerFactory;
  *
  */
 public class InventoryServiceShim implements IContainerListener,
-        IMessageListener, ISwitchStateListener, IOFStatisticsListener {
+        IMessageListener, ISwitchStateListener, IOFStatisticsListener, IContainerAware {
     protected static final Logger logger = LoggerFactory
             .getLogger(InventoryServiceShim.class);
     private IController controller = null;
@@ -139,7 +140,7 @@ public class InventoryServiceShim implements IContainerListener,
     }
 
     void setInventoryShimExternalListener(IInventoryShimExternalListener s) {
-        logger.trace("Set inventoryShimExternalListener");
+        logger.trace("Set inventoryShimExternalListener {}", s);
         if ((this.inventoryShimExternalListeners != null)
                 && !this.inventoryShimExternalListeners.contains(s)) {
             this.inventoryShimExternalListeners.add(s);
@@ -147,6 +148,7 @@ public class InventoryServiceShim implements IContainerListener,
     }
 
     void unsetInventoryShimExternalListener(IInventoryShimExternalListener s) {
+        logger.trace("Unset inventoryShimExternalListener {}", s);
         if ((this.inventoryShimExternalListeners != null)
                 && this.inventoryShimExternalListeners.contains(s)) {
             this.inventoryShimExternalListeners.remove(s);
@@ -583,4 +585,43 @@ public class InventoryServiceShim implements IContainerListener,
     public void tableStatisticsRefreshed(Long switchId, List<OFStatistics> tables) {
         // Nothing to do
     }
+
+    @Override
+    public void containerCreate(String containerName) {
+        // Nothing to do
+    }
+
+    @Override
+    public void containerDestroy(String containerName) {
+        Set<NodeConnector> removeNodeConnectorSet = new HashSet<NodeConnector>();
+        Set<Node> removeNodeSet = new HashSet<Node>();
+        for (Map.Entry<NodeConnector, Set<String>> entry : nodeConnectorContainerMap.entrySet()) {
+            Set<String> ncContainers = entry.getValue();
+            if (ncContainers.contains(containerName)) {
+                NodeConnector nodeConnector = entry.getKey();
+                removeNodeConnectorSet.add(nodeConnector);
+            }
+        }
+        for (Map.Entry<Node, Set<String>> entry : nodeContainerMap.entrySet()) {
+            Set<String> nodeContainers = entry.getValue();
+            if (nodeContainers.contains(containerName)) {
+                Node node = entry.getKey();
+                removeNodeSet.add(node);
+            }
+        }
+        for (NodeConnector nodeConnector : removeNodeConnectorSet) {
+            Set<String> ncContainers = nodeConnectorContainerMap.get(nodeConnector);
+            ncContainers.remove(containerName);
+            if (ncContainers.isEmpty()) {
+                nodeConnectorContainerMap.remove(nodeConnector);
+            }
+        }
+        for (Node node : removeNodeSet) {
+            Set<String> nodeContainers = nodeContainerMap.get(node);
+            nodeContainers.remove(containerName);
+            if (nodeContainers.isEmpty()) {
+                nodeContainerMap.remove(node);
+            }
+        }
+    }
 }
index b877eb0ee793626d2990e24855052653466aa4ba..d7bf2e22586188f578c72e02d9c453551a380ccd 100644 (file)
@@ -27,6 +27,7 @@ import org.opendaylight.controller.sal.action.Action;
 import org.opendaylight.controller.sal.action.ActionType;
 import org.opendaylight.controller.sal.action.Output;
 import org.opendaylight.controller.sal.core.ContainerFlow;
+import org.opendaylight.controller.sal.core.IContainerAware;
 import org.opendaylight.controller.sal.core.IContainerListener;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
@@ -55,7 +56,7 @@ import org.slf4j.LoggerFactory;
  * Read Service shim layer which is in charge of filtering the flow statistics
  * based on container. It is a Global instance.
  */
-public class ReadServiceFilter implements IReadServiceFilter, IContainerListener, IOFStatisticsListener {
+public class ReadServiceFilter implements IReadServiceFilter, IContainerListener, IOFStatisticsListener, IContainerAware {
     private static final Logger logger = LoggerFactory
             .getLogger(ReadServiceFilter.class);
     private IController controller = null;
@@ -632,4 +633,17 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener
             l.getValue().nodeTableStatisticsUpdated(node, tableStatsList);
         }
     }
+
+    @Override
+    public void containerCreate(String containerName) {
+        // do nothing
+    }
+
+    @Override
+    public void containerDestroy(String containerName) {
+        containerToNc.remove(containerName);
+        containerToNode.remove(containerName);
+        containerToNt.remove(containerName);
+        containerFlows.remove(containerName);
+    }
 }
index 400e9e869218ad60ea8a0898800e666ac03f7ef4..86583ace0a0f540b5347accdeb3992dcb30961fd 100644 (file)
@@ -32,15 +32,11 @@ import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimExtern
 import org.opendaylight.controller.protocol_plugin.openflow.IOFStatisticsManager;
 import org.opendaylight.controller.protocol_plugin.openflow.IRefreshInternalProvider;
 import org.opendaylight.controller.protocol_plugin.openflow.ITopologyServiceShimListener;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import org.opendaylight.controller.sal.core.Bandwidth;
 import org.opendaylight.controller.sal.core.Config;
 import org.opendaylight.controller.sal.core.ContainerFlow;
 import org.opendaylight.controller.sal.core.Edge;
+import org.opendaylight.controller.sal.core.IContainerAware;
 import org.opendaylight.controller.sal.core.IContainerListener;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
@@ -49,6 +45,10 @@ import org.opendaylight.controller.sal.core.State;
 import org.opendaylight.controller.sal.core.UpdateType;
 import org.opendaylight.controller.sal.topology.TopoEdgeUpdate;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The class describes a shim layer that relays the topology events from
@@ -57,7 +57,7 @@ import org.opendaylight.controller.sal.utils.GlobalConstants;
  */
 public class TopologyServiceShim implements IDiscoveryListener,
         IContainerListener, CommandProvider, IRefreshInternalProvider,
-        IInventoryShimExternalListener {
+        IInventoryShimExternalListener, IContainerAware {
     protected static final Logger logger = LoggerFactory
             .getLogger(TopologyServiceShim.class);
     private ConcurrentMap<String, ITopologyServiceShimListener> topologyServiceShimListeners = new ConcurrentHashMap<String, ITopologyServiceShimListener>();
@@ -916,4 +916,29 @@ public class TopologyServiceShim implements IDiscoveryListener,
             break;
         }
     }
+
+    @Override
+    public void containerCreate(String containerName) {
+        // do nothing
+    }
+
+    @Override
+    public void containerDestroy(String containerName) {
+        Set<NodeConnector> removeNodeConnectorSet = new HashSet<NodeConnector>();
+        for (Map.Entry<NodeConnector, List<String>> entry : containerMap.entrySet()) {
+            List<String> ncContainers = entry.getValue();
+            if (ncContainers.contains(containerName)) {
+                NodeConnector nodeConnector = entry.getKey();
+                removeNodeConnectorSet.add(nodeConnector);
+            }
+        }
+        for (NodeConnector nodeConnector : removeNodeConnectorSet) {
+            List<String> ncContainers = containerMap.get(nodeConnector);
+            ncContainers.remove(containerName);
+            if (ncContainers.isEmpty()) {
+                containerMap.remove(nodeConnector);
+            }
+        }
+        edgeMap.remove(containerName);
+    }
 }