Merge "Make FRM cleanup only local entries"
authorAlessandro Boch <aboch@cisco.com>
Fri, 27 Sep 2013 00:44:29 +0000 (00:44 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 27 Sep 2013 00:44:29 +0000 (00:44 +0000)
1  2 
opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java

index c2d1f46737683b4a0eb8a7339c7677ee7f0ca961,3ee407de0238d09f776e05a1d46724c9b95336c0..defe9b4a82f6a9f8a2c9e48c94d54ec0d108568b
@@@ -28,6 -28,7 +28,6 @@@ import java.util.concurrent.ConcurrentM
  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;
@@@ -782,16 -783,6 +782,16 @@@ public class ForwardingRulesManager imp
          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);
       * If requested, a copy of each original flow entry will be stored in the
       * inactive list so that it can be re-applied when needed (This is typically
       * the case when running in the default container and controller moved to
-      * container mode)
+      * container mode) NOTE WELL: The routine as long as does a bulk change will
+      * operate only on the entries for nodes locally attached so to avoid
+      * redundant operations initiated by multiple nodes
       *
       * @param preserveFlowEntries
       *            if true, a copy of each original entry is stored in the
  
          // Now remove the entries
          for (FlowEntryInstall flowEntryHw : toRemove) {
-             Status status = this.removeEntryInternal(flowEntryHw, false);
-             if (!status.isSuccess()) {
-                 log.warn("Failed to remove entry: {}. The failure is: {}", flowEntryHw, status.getDescription());
+             Node n = flowEntryHw.getNode();
+             if (n != null && connectionManager.getLocalityStatus(n) == ConnectionLocality.LOCAL) {
+                 Status status = this.removeEntryInternal(flowEntryHw, false);
+                 if (!status.isSuccess()) {
+                     log.warn("Failed to remove entry: {}. The failure is: {}", flowEntryHw, status.getDescription());
+                 }
+             } else {
+                 log.debug("Not removing entry {} because not connected locally, the remote guy will do it's job",
+                         flowEntryHw);
              }
          }
      }
  
      @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;
      }
          uninstallAllFlowEntries(false);
          // Shutdown executor
          this.executor.shutdownNow();
+         // Now walk all the workMonitor and wake up the one sleeping because
+         // destruction is happening
+         for (FlowEntryDistributionOrder fe : workMonitor.keySet()) {
+             FlowEntryDistributionOrderFutureTask task = workMonitor.get(fe);
+             task.cancel(true);
+         }
      }
  
      public void setFlowProgrammerService(IFlowProgrammerService service) {
          }
      }
  
 +    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);
          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