Fix ConsistentMapException.Interrupted and NullPointerException

- Moving time-consuming packet processing to a separate thread
- Re-use the group information when dealing groupMissing instead of query again

Change-Id: I01f1b43260f22dcb969a105f16d04d79c722146e
diff --git a/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 156240a..5b520b9 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -146,6 +146,7 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -278,6 +279,7 @@
     private ScheduledExecutorService hostEventExecutor;
     private ScheduledExecutorService routeEventExecutor;
     private ScheduledExecutorService mcastEventExecutor;
+    private ExecutorService packetExecutor;
 
     Map<DeviceId, DefaultGroupHandler> groupHandlerMap = new ConcurrentHashMap<>();
     /**
@@ -377,6 +379,7 @@
         hostEventExecutor = Executors.newSingleThreadScheduledExecutor(groupedThreads("sr-event-host", "%d", log));
         routeEventExecutor = Executors.newSingleThreadScheduledExecutor(groupedThreads("sr-event-route", "%d", log));
         mcastEventExecutor = Executors.newSingleThreadScheduledExecutor(groupedThreads("sr-event-mcast", "%d", log));
+        packetExecutor = Executors.newSingleThreadExecutor(groupedThreads("sr-packet", "%d", log));
 
         log.debug("Creating EC map nsnextobjectivestore");
         EventuallyConsistentMapBuilder<DestinationSetNextObjectiveStoreKey, NextNeighbors>
@@ -530,6 +533,7 @@
         hostEventExecutor.shutdown();
         routeEventExecutor.shutdown();
         mcastEventExecutor.shutdown();
+        packetExecutor.shutdown();
 
         cfgService.removeListener(cfgListener);
         cfgService.unregisterConfigFactory(deviceConfigFactory);
@@ -1036,7 +1040,10 @@
     private class InternalPacketProcessor implements PacketProcessor {
         @Override
         public void process(PacketContext context) {
+            packetExecutor.execute(() -> processPacketInternal(context));
+        }
 
+        private void processPacketInternal(PacketContext context) {
             if (context.isHandled()) {
                 return;
             }