[SDFAB-158] eNB not able to get IP through fabric

After subsequent calls to configureNetwork() we dont set
the onComplete handler and due to this the queue events
are never processed. Most of the times everything works
despite this evident bug because in the DeviceConfiguration
we parse in a greedy way all the netcfg. Sometimes this can
fail if all the netcfg is not immediately available.

Likely fix [SDFAB-113] SR sometimes does not create flows and groups

Change-Id: Iebfa9bf9b1cc29af112bf38895441cbac47c7774
diff --git a/impl/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/impl/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index ef5a465..f96e9d0 100644
--- a/impl/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/impl/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -17,6 +17,7 @@
 
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Sets;
@@ -539,20 +540,32 @@
         linkHandler.init();
         l2TunnelHandler.init();
 
-        synchronized (networkConfigCompletionLock) {
-            networkConfigCompletion.whenComplete((value, ex) -> {
-                //setting to null for easier fall through
-                networkConfigCompletion = null;
-                //process all queued events
-                queuedEvents.forEach(event -> {
-                    mainEventExecutor.execute(new InternalEventHandler(event));
-                });
-            });
-        }
+        drainEvents();
 
         log.info("Started");
     }
 
+    // Drain buffered events
+    private void drainEvents() {
+        synchronized (networkConfigCompletionLock) {
+            final List<Event> processedEvents = Lists.newArrayList();
+            if (networkConfigCompletion != null) {
+                networkConfigCompletion.whenComplete((value, ex) -> {
+                    //setting to null for easier fall through
+                    networkConfigCompletion = null;
+                    //process all queued events
+                    queuedEvents.forEach(event -> {
+                        mainEventExecutor.execute(new InternalEventHandler(event));
+                        processedEvents.add(event);
+                    });
+                    // Removes all
+                    queuedEvents.removeAll(processedEvents);
+                    processedEvents.clear();
+                });
+            }
+        }
+    }
+
     KryoNamespace.Builder createSerializer() {
         return new KryoNamespace.Builder()
                 .register(KryoNamespaces.API)
@@ -886,7 +899,7 @@
 
     @Override
     public void rerouteNetwork() {
-        cfgListener.configureNetwork();
+        cfgListener.configureNetworkAndDrainEvents();
     }
 
     @Override
@@ -1517,13 +1530,13 @@
                     if (configClass.equals(SegmentRoutingAppConfig.class)) {
                         appCfgHandler.processAppConfigAdded(netcfgEvent);
                         log.info("App config event .. configuring network");
-                        cfgListener.configureNetwork();
+                        cfgListener.configureNetworkAndDrainEvents();
                     } else if (configClass.equals(SegmentRoutingDeviceConfig.class)) {
                         log.info("Segment Routing Device Config added for {}", event.subject());
-                        cfgListener.configureNetwork();
+                        cfgListener.configureNetworkAndDrainEvents();
                     } else if (configClass.equals(InterfaceConfig.class)) {
                         log.info("Interface Config added for {}", event.subject());
-                        cfgListener.configureNetwork();
+                        cfgListener.configureNetworkAndDrainEvents();
                     } else {
                         log.error("Unhandled config class: {}", configClass);
                     }
@@ -1533,7 +1546,7 @@
                     if (configClass.equals(SegmentRoutingAppConfig.class)) {
                         appCfgHandler.processAppConfigUpdated(netcfgEvent);
                         log.info("App config event .. configuring network");
-                        cfgListener.configureNetwork();
+                        cfgListener.configureNetworkAndDrainEvents();
                     } else if (configClass.equals(SegmentRoutingDeviceConfig.class)) {
                         log.info("Segment Routing Device Config updated for {}", event.subject());
                         createOrUpdateDeviceConfiguration();
@@ -1551,7 +1564,7 @@
                     if (configClass.equals(SegmentRoutingAppConfig.class)) {
                         appCfgHandler.processAppConfigRemoved(netcfgEvent);
                         log.info("App config event .. configuring network");
-                        cfgListener.configureNetwork();
+                        cfgListener.configureNetworkAndDrainEvents();
                     } else if (configClass.equals(SegmentRoutingDeviceConfig.class)) {
                         // TODO Handle sr device config removal
                         log.info("SegmentRoutingDeviceConfig removal is not handled in current implementation");
@@ -1858,6 +1871,15 @@
 
         }
 
+        /**
+         * Reads network config, initializes related data structure accordingly
+         * and drain buffered events if needed.
+         */
+        void configureNetworkAndDrainEvents() {
+            configureNetwork();
+            drainEvents();
+        }
+
         @Override
         public void event(NetworkConfigEvent event) {
             if (mainEventExecutor == null) {