Introduce allowlist for back to back duplicate events

If there are two duplicate back to back role requests
DeviceTaskExectur drops the duplicate response if they
are spaced by an interval < 1s. This patch introduces an
allowlist for event types that should not be dropped
by the back to back policy.

This patch fixes one scenario that led to SDFAB-1025

Change-Id: Ic62ba56228c9c0c2b368e8e68ff50d11e2dc4249
diff --git a/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/DeviceTaskExecutor.java b/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/DeviceTaskExecutor.java
index 6f90256..30e754a 100644
--- a/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/DeviceTaskExecutor.java
+++ b/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/DeviceTaskExecutor.java
@@ -75,15 +75,22 @@
                     return new TaskQueue();
                 }
             });
+    /**
+     * Type of tasks allowed to be back to back.
+     */
+    private final Set<T> allowList;
 
     /**
-     * Creates a new executor with the given delegate executor service.
+     * Creates a new executor with the given delegate executor service
+     * and the allowed back to back task types.
      *
      * @param delegate executor service
+     * @param allowed tasks allowed to be back to back
      */
-    DeviceTaskExecutor(ExecutorService delegate) {
+    DeviceTaskExecutor(ExecutorService delegate, Set<T> allowed) {
         checkNotNull(delegate);
         this.delegate = delegate;
+        this.allowList = allowed;
     }
 
     /**
@@ -108,7 +115,7 @@
         final DeviceTask task = new DeviceTask(deviceId, type, runnable);
         deviceLocks.get(deviceId).lock();
         try {
-            if (taskQueues.get(deviceId).isBackToBackDuplicate(type)) {
+            if (taskQueues.get(deviceId).isBackToBackDuplicate(type) && !allowList.contains(type)) {
                 if (log.isDebugEnabled()) {
                     log.debug("Dropping back-to-back duplicate task {} for {}",
                               type, deviceId);
diff --git a/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/GeneralDeviceProvider.java b/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/GeneralDeviceProvider.java
index 78ab98a..f684d31 100644
--- a/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/GeneralDeviceProvider.java
+++ b/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/GeneralDeviceProvider.java
@@ -204,7 +204,7 @@
     public void activate(ComponentContext context) {
         mainExecutor = newFixedThreadPool(CORE_POOL_SIZE, groupedThreads(
                 "onos/gdp", "%d", log));
-        taskExecutor = new DeviceTaskExecutor<>(mainExecutor);
+        taskExecutor = new DeviceTaskExecutor<>(mainExecutor, GDP_ALLOWLIST);
         providerService = providerRegistry.register(this);
         componentConfigService.registerProperties(getClass());
         coreService.registerApplication(APP_NAME);
@@ -587,6 +587,9 @@
         NOT_MASTER,
     }
 
+    private static final Set<TaskType> GDP_ALLOWLIST = Sets.newHashSet(TaskType.ROLE_MASTER, TaskType.ROLE_NONE,
+            TaskType.ROLE_STANDBY, TaskType.NOT_MASTER);
+
     private void submitTask(DeviceId deviceId, TaskType taskType) {
         taskExecutor.submit(deviceId, taskType, taskRunnable(deviceId, taskType));
     }