Fix for empty flooding groups due to bucket add/remove commands being reordered, and
triggered by port up/down events very close to each other.

Change-Id: Ibbd7cc6eb6df35396175619d95439acd6da904b8
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index a70ff63..5d04301 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -1288,7 +1288,7 @@
                 log.warn(e.getMessage() + " Aborting processDeviceAdded.");
                 return;
             }
-            log.debug("updating groupHandlerMap with new config for device: {}",
+            log.debug("updating groupHandlerMap with new grpHdlr for device: {}",
                     deviceId);
             groupHandlerMap.put(deviceId, groupHandler);
         }
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index 848e2ca..300f2a2 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -621,7 +621,7 @@
         if (nextId == -1) {
             if (portUp) {
                 log.debug("**Creating flooding group for first port enabled in"
-                        + " subnet {} on dev {} port {}", vlanId, deviceId, port);
+                        + " vlan {} on dev {} port {}", vlanId, deviceId, port);
                 createBcastGroupFromVlan(vlanId, Collections.singleton(port));
             } else {
                 log.warn("Could not find flooding group for subnet {} on dev:{} when"
@@ -1016,8 +1016,8 @@
             );
         NextObjective nextObj = nextObjBuilder.add(context);
         flowObjectiveService.next(deviceId, nextObj);
-        log.debug("createBcastGroupFromVlan: Submitted next objective {} in device {}",
-                  nextId, deviceId);
+        log.debug("createBcastGroupFromVlan: Submitted next objective {} "
+                + "for vlan: {} in device {}", nextId, vlanId, deviceId);
 
         vlanNextObjStore.put(key, nextId);
     }
diff --git a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java
index 4bd4feb..09d3a24 100644
--- a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java
+++ b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.net.flowobjective.impl;
 
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import org.apache.felix.scr.annotations.Activate;
@@ -138,7 +139,7 @@
     // instance, via the DistributedFlowObjectiveStore.
     private final Map<Integer, Set<PendingFlowObjective>> pendingForwards =
             Maps.newConcurrentMap();
-    private final Map<Integer, Set<PendingFlowObjective>> pendingNexts =
+    private final Map<Integer, List<PendingFlowObjective>> pendingNexts =
             Maps.newConcurrentMap();
 
     // local store to track which nextObjectives were sent to which device
@@ -317,7 +318,7 @@
                 pendingNexts.compute(next.id(), (id, pending) -> {
                     PendingFlowObjective pendfo = new PendingFlowObjective(deviceId, next);
                     if (pending == null) {
-                        return Sets.newHashSet(pendfo);
+                        return Lists.newArrayList(pendfo);
                     } else {
                         pending.add(pendfo);
                         return pending;
@@ -550,17 +551,18 @@
                 }
 
                 // now check for pending next-objectives
+                List<PendingFlowObjective> pendNexts;
                 synchronized (pendingNexts) {
                     // needs to be synchronized for queueObjective lookup
-                    pending = pendingNexts.remove(event.subject());
+                    pendNexts = pendingNexts.remove(event.subject());
                 }
-                if (pending == null) {
+                if (pendNexts == null) {
                     log.debug("No next objectives pending for this "
                             + "obj event {}", event);
                 } else {
                     log.debug("Processing {} pending next objectives for nextId {}",
-                              pending.size(), event.subject());
-                    pending.forEach(p -> getDevicePipeliner(p.deviceId())
+                              pendNexts.size(), event.subject());
+                    pendNexts.forEach(p -> getDevicePipeliner(p.deviceId())
                                     .next((NextObjective) p.flowObjective()));
                 }
             }
@@ -666,7 +668,7 @@
         }
 
         for (Integer nextId : pendingNexts.keySet()) {
-            Set<PendingFlowObjective> pnext = pendingNexts.get(nextId);
+            List<PendingFlowObjective> pnext = pendingNexts.get(nextId);
             StringBuilder pend = new StringBuilder();
             pend.append("NextId: ")
                     .append(nextId);
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
index 2d960ce..1fdf2ab 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
@@ -721,7 +721,7 @@
             if (matchInPortTmacTable()) {
                 selector.matchInPort(pnum);
             } else {
-                log.info("Pipeline does not support IN_PORT matching in TMAC table, " +
+                log.debug("Pipeline does not support IN_PORT matching in TMAC table, " +
                         "ignoring the IN_PORT criteria");
             }
         }
@@ -766,7 +766,7 @@
             if (matchInPortTmacTable()) {
                 selector.matchInPort(pnum);
             } else {
-                log.info("Pipeline does not support IN_PORT matching in TMAC table, " +
+                log.debug("Pipeline does not support IN_PORT matching in TMAC table, " +
                         "ignoring the IN_PORT criteria");
             }
         }
@@ -811,7 +811,7 @@
             if (matchInPortTmacTable()) {
                 selector.matchInPort(pnum);
             } else {
-                log.info("Pipeline does not support IN_PORT matching in TMAC table, " +
+                log.debug("Pipeline does not support IN_PORT matching in TMAC table, " +
                         "ignoring the IN_PORT criteria");
             }
         }