Decouple IContainerListener to avoid parallel computation in cluster
[controller.git] / opendaylight / forwardingrulesmanager / implementation / src / main / java / org / opendaylight / controller / forwardingrulesmanager / internal / ForwardingRulesManager.java
index 3c936de769d6a22f426b01bab868593eefb899e2..a77224af8a172ed396addb3dbeab3c2dd8939361 100644 (file)
@@ -28,7 +28,6 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
 import java.util.concurrent.LinkedBlockingQueue;
 
 import org.eclipse.osgi.framework.console.CommandInterpreter;
@@ -60,7 +59,7 @@ import org.opendaylight.controller.sal.action.PopVlan;
 import org.opendaylight.controller.sal.core.Config;
 import org.opendaylight.controller.sal.core.ContainerFlow;
 import org.opendaylight.controller.sal.core.IContainer;
-import org.opendaylight.controller.sal.core.IContainerListener;
+import org.opendaylight.controller.sal.core.IContainerLocalListener;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.core.Property;
@@ -98,7 +97,7 @@ import org.slf4j.LoggerFactory;
 public class ForwardingRulesManager implements
         IForwardingRulesManager,
         PortGroupChangeListener,
-        IContainerListener,
+        IContainerLocalListener,
         ISwitchManagerAware,
         IConfigurationContainerAware,
         IInventoryListener,
@@ -783,6 +782,16 @@ public class ForwardingRulesManager implements
         return true;
     }
 
+    private ConcurrentMap.Entry<Integer, FlowConfig> getStaticFlowEntry(String name, Node node) {
+        for (ConcurrentMap.Entry<Integer, FlowConfig> flowEntry : staticFlows.entrySet()) {
+            FlowConfig flowConfig = flowEntry.getValue();
+            if (flowConfig.isByNameAndNodeIdEqual(name, node)) {
+                return flowEntry;
+            }
+        }
+        return null;
+    }
+
     private void updateLocalDatabase(FlowEntryInstall entry, boolean add) {
         // Update the software view
         updateSwViewes(entry, add);
@@ -1357,9 +1366,6 @@ public class ForwardingRulesManager implements
             clusterContainerService.createCache("frm.staticFlows",
                     EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
 
-            clusterContainerService.createCache("frm.flowsSaveEvent",
-                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
-
             clusterContainerService.createCache("frm.staticFlowsOrdinal",
                     EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
 
@@ -1947,10 +1953,9 @@ public class ForwardingRulesManager implements
 
     @Override
     public FlowConfig getStaticFlow(String name, Node node) {
-        for (ConcurrentMap.Entry<Integer, FlowConfig> entry : staticFlows.entrySet()) {
-            if (entry.getValue().isByNameAndNodeIdEqual(name, node)) {
-                return entry.getValue();
-            }
+        ConcurrentMap.Entry<Integer, FlowConfig> entry = getStaticFlowEntry(name, node);
+        if(entry != null) {
+            return entry.getValue();
         }
         return null;
     }
@@ -2508,6 +2513,7 @@ public class ForwardingRulesManager implements
                             log.warn("Dequeued null event");
                             continue;
                         }
+                        log.trace("Dequeued {} event", event.getClass().getSimpleName());
                         if (event instanceof NodeUpdateEvent) {
                             NodeUpdateEvent update = (NodeUpdateEvent) event;
                             Node node = update.getNode();
@@ -3032,6 +3038,36 @@ public class ForwardingRulesManager implements
         }
     }
 
+    public void _frmProcessErrorEvent(CommandInterpreter ci) throws UnknownHostException {
+        Node node = null;
+        long reqId = 0L;
+        String nodeId = ci.nextArgument();
+        if (nodeId == null) {
+            ci.print("Node id not specified");
+            return;
+        }
+        String requestId = ci.nextArgument();
+        if (requestId == null) {
+            ci.print("Request id not specified");
+            return;
+        }
+        try {
+            node = NodeCreator.createOFNode(Long.valueOf(nodeId));
+        } catch (NumberFormatException e) {
+            ci.print("Node id not a number");
+            return;
+        }
+        try {
+            reqId = Long.parseLong(requestId);
+        } catch (NumberFormatException e) {
+            ci.print("Request id not a number");
+            return;
+        }
+        // null for error object is good enough for now
+        ErrorReportedEvent event = new ErrorReportedEvent(reqId, node, null);
+        this.processErrorEvent(event);
+    }
+
     @Override
     public void flowRemoved(Node node, Flow flow) {
         log.trace("Received flow removed notification on {} for {}", node, flow);
@@ -3101,6 +3137,15 @@ public class ForwardingRulesManager implements
         if (target != null) {
             // This was a flow install, update database
             this.updateLocalDatabase(target, false);
+            // also update the config
+            if(FlowConfig.STATICFLOWGROUP.equals(target.getGroupName())) {
+                ConcurrentMap.Entry<Integer, FlowConfig> staticFlowEntry = getStaticFlowEntry(target.getFlowName(),target.getNode());
+                // staticFlowEntry should never be null.
+                // the null check is just an extra defensive check.
+                if(staticFlowEntry != null) {
+                    staticFlows.remove(staticFlowEntry.getKey());
+                }
+            }
         }
 
         // Notify listeners