[SDFAB-20] Prevent listeners ejection and the stop of the group polling

Offload listeners processing to external executors to prevent
the listener ejection due to time consuming processing

In future, we may want to extend the same fix to the
HostManager and NetworkConfigHostProvider

Additionally, avoid the propagation of the exceptions in GroupDriverProvider
which leads to the cancellation of the peridioc poll task

Change-Id: I8ea4ec9fda1ccc48bbd3855fd443ee8760cbbb60
diff --git a/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java b/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java
index 39ef3d9..363876c 100644
--- a/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java
+++ b/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java
@@ -508,26 +508,29 @@
 
         @Override
         public void event(DeviceEvent event) {
-            switch (event.type()) {
-                case DEVICE_REMOVED:
-                case DEVICE_AVAILABILITY_CHANGED:
-                    DeviceId deviceId = event.subject().id();
-                    if (!deviceService.isAvailable(deviceId)) {
-                        BasicDeviceConfig cfg = netCfgService.getConfig(deviceId, BasicDeviceConfig.class);
-                        //if purgeOnDisconnection is set for the device or it's a global configuration
-                        // lets remove the meters.
-                        boolean purge = cfg != null && cfg.isPurgeOnDisconnectionConfigured() ?
-                                cfg.purgeOnDisconnection() : purgeOnDisconnection;
-                        if (purge) {
-                            log.info("PurgeOnDisconnection is requested for device {}, " +
-                                             "removing meters", deviceId);
-                            store.purgeMeter(deviceId);
+            DeviceId deviceId = event.subject().id();
+            meterInstallers.execute(() -> {
+                switch (event.type()) {
+                    case DEVICE_REMOVED:
+                    case DEVICE_AVAILABILITY_CHANGED:
+                        if (!deviceService.isAvailable(deviceId)) {
+                            BasicDeviceConfig cfg = netCfgService.getConfig(deviceId, BasicDeviceConfig.class);
+                            //if purgeOnDisconnection is set for the device or it's a global configuration
+                            // lets remove the meters.
+                            boolean purge = cfg != null && cfg.isPurgeOnDisconnectionConfigured() ?
+                                    cfg.purgeOnDisconnection() : purgeOnDisconnection;
+                            if (purge) {
+                                log.info("PurgeOnDisconnection is requested for device {}, " +
+                                        "removing meters", deviceId);
+                                store.purgeMeter(deviceId);
+                            }
                         }
-                    }
-                    break;
-                default:
-                    break;
-            }
+                        break;
+                    default:
+                        break;
+                }
+            }, deviceId.hashCode());
+
         }
     }