[CORD-2483] Deleting multiple sinks does not clean all flows and groups

Rationale: Let's assume we have a working group with
multiple sinks. We try to delete the sinks all together,
also in this case for each sink a sink removed event is
generated. For each event we create a new next objective
removing the ports no more needed.

Solution is related to the previous patch (group editing).
Failure scenario:

Sink1 removed -> fwdObj A -> Next B

McastHandler store has been updated at this point.

Sink2 removed -> remove fwdObj A

The remove operations is executed immediately but
the Next B could not exist at this point -> flow
installation failed

Change-Id: Icf568b26b2f3ae3feb935b13038db6195125a5c4
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/McastHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/McastHandler.java
index e77ba97..ce2c2da 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/McastHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/McastHandler.java
@@ -581,13 +581,14 @@
         existingPorts.remove(port);
 
         NextObjective newNextObj;
+        ObjectiveContext context;
         ForwardingObjective fwdObj;
         if (existingPorts.isEmpty()) {
-            // If this is the last sink, remove flows and groups
+            // If this is the last sink, remove flows and last bucket
             // NOTE: Rely on GroupStore garbage collection rather than explicitly
             //       remove L3MG since there might be other flows/groups refer to
             //       the same L2IG
-            ObjectiveContext context = new DefaultObjectiveContext(
+            context = new DefaultObjectiveContext(
                     (objective) -> log.debug("Successfully remove {} on {}/{}, vlan {}",
                             mcastIp, deviceId, port.toLong(), assignedVlan),
                     (objective, error) ->
@@ -595,21 +596,25 @@
                                     mcastIp, deviceId, port.toLong(), assignedVlan, error));
             fwdObj = fwdObjBuilder(mcastIp, assignedVlan, nextObj.id()).remove(context);
             mcastNextObjStore.remove(mcastStoreKey);
-            srManager.flowObjectiveService.forward(deviceId, fwdObj);
         } else {
             // If this is not the last sink, update flows and groups
-            ObjectiveContext context = new DefaultObjectiveContext(
+            context = new DefaultObjectiveContext(
                     (objective) -> log.debug("Successfully update {} on {}/{}, vlan {}",
                             mcastIp, deviceId, port.toLong(), assignedVlan),
                     (objective, error) ->
                             log.warn("Failed to update {} on {}/{}, vlan {}: {}",
                                     mcastIp, deviceId, port.toLong(), assignedVlan, error));
-            newNextObj = nextObjBuilder(mcastIp, assignedVlan, existingPorts, null).add();
+            // Here we store the next objective with the remaining port
+            newNextObj = nextObjBuilder(mcastIp, assignedVlan,
+                                        existingPorts, nextObj.id()).removeFromExisting();
             fwdObj = fwdObjBuilder(mcastIp, assignedVlan, newNextObj.id()).add(context);
             mcastNextObjStore.put(mcastStoreKey, newNextObj);
-            srManager.flowObjectiveService.next(deviceId, newNextObj);
-            srManager.flowObjectiveService.forward(deviceId, fwdObj);
         }
+        // Let's modify the next objective removing the bucket
+        newNextObj = nextObjBuilder(mcastIp, assignedVlan,
+                                    ImmutableSet.of(port), nextObj.id()).removeFromExisting();
+        srManager.flowObjectiveService.next(deviceId, newNextObj);
+        srManager.flowObjectiveService.forward(deviceId, fwdObj);
         return existingPorts.isEmpty();
     }