Misc fixes in openflow provider subsystem

Change-Id: I5e6ab619f66ca71badc25efc7be7560070639051
(cherry picked from commit 91e1d737f6c60b48d7b2eb03a524138db1d68e8c)
diff --git a/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java b/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
index 3b12fdb..abede47 100644
--- a/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
+++ b/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
@@ -788,7 +788,7 @@
                             OFPortStatsReply portStatsReply = (OFPortStatsReply) msg;
                             List<OFPortStatsEntry> portStatsReplyList = portStatsReplies.get(dpid);
                             if (portStatsReplyList == null) {
-                                portStatsReplyList = Lists.newArrayList();
+                                portStatsReplyList = Lists.newCopyOnWriteArrayList();
                             }
                             portStatsReplyList.addAll(portStatsReply.getEntries());
                             portStatsReplies.put(dpid, portStatsReplyList);
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowStatsCollector.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowStatsCollector.java
index 38ebac5..88ba50b 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowStatsCollector.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowStatsCollector.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.provider.of.flow.impl;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import org.onlab.util.SharedExecutors;
 import org.onosproject.openflow.controller.OpenFlowSwitch;
 import org.onosproject.openflow.controller.RoleState;
@@ -52,7 +53,7 @@
      */
     FlowStatsCollector(Timer timer, OpenFlowSwitch sw, int pollInterval) {
         this.timer = timer;
-        this.sw = sw;
+        this.sw = checkNotNull(sw, "Null switch");
         this.pollInterval = pollInterval;
     }
 
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
index a3a0738..1482add 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -19,8 +19,11 @@
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.RemovalCause;
 import com.google.common.cache.RemovalNotification;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -217,6 +220,7 @@
     }
 
     private void createCollector(OpenFlowSwitch sw) {
+        checkNotNull(sw, "Null switch");
         if (adaptiveFlowSampling) {
             // NewAdaptiveFlowStatsCollector Constructor
             NewAdaptiveFlowStatsCollector fsc =
@@ -339,10 +343,17 @@
     public void executeBatch(FlowRuleBatchOperation batch) {
         checkNotNull(batch);
 
-        pendingBatches.put(batch.id(), new InternalCacheEntry(batch));
-
         Dpid dpid = Dpid.dpid(batch.deviceId().uri());
         OpenFlowSwitch sw = controller.getSwitch(dpid);
+
+        // If switch no longer exists, simply return.
+        if (sw == null) {
+            Set<FlowRule> failures = ImmutableSet.copyOf(Lists.transform(batch.getOperations(), e -> e.target()));
+            providerService.batchOperationCompleted(batch.id(),
+                                                    new CompletedBatchOperation(false, failures, batch.deviceId()));
+            return;
+        }
+        pendingBatches.put(batch.id(), new InternalCacheEntry(batch));
         OFFlowMod mod;
         for (FlowRuleBatchEntry fbe : batch.getOperations()) {
             // flow is the third party privacy flow
diff --git a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterStatsCollector.java b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterStatsCollector.java
index a11847a..552e5ec 100644
--- a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterStatsCollector.java
+++ b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterStatsCollector.java
@@ -56,6 +56,11 @@
 
     @Override
     public void run(Timeout timeout) throws Exception {
+        if (!sw.isConnected()) {
+            log.debug("Switch {} disconnected. Aborting meter stats collection", sw.getStringId());
+            return;
+        }
+
         log.trace("Collecting stats for {}", sw.getStringId());
 
         sendMeterStatistic();
diff --git a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java
index 952a47f..436b071 100644
--- a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java
+++ b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java
@@ -204,7 +204,7 @@
     }
 
     private void createStatsCollection(OpenFlowSwitch sw) {
-        if (isMeterSupported(sw)) {
+        if (sw != null && isMeterSupported(sw)) {
             MeterStatsCollector msc = new MeterStatsCollector(sw, POLL_INTERVAL);
             msc.start();
             stopCollectorIfNeeded(collectors.put(new Dpid(sw.getId()), msc));