[ONOS-3724] Fix the Cbench regression issue

Control message monitoring brings some overhead to controller.
In an extreme stressing environment (e.g., running Cbench),
it leads potential performance degradation.

This commit tries to mitigate the Cbench regression with two steps:
1. improve the monitoring performance by assigning more # of
threads in each thread group.
2. make the control message listening feature optional.

Change-Id: I4f7361b7c598c6de71d390eab78a20ada381d4dd
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
index a877a66..182935a 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -92,10 +92,10 @@
     protected OFFeaturesReply features;
     protected OFDescStatsReply desc;
 
-    protected Set<OpenFlowEventListener> ofEventListener = new CopyOnWriteArraySet<>();
+    protected Set<OpenFlowEventListener> ofOutgoingMsgListener = new CopyOnWriteArraySet<>();
 
     protected ExecutorService executorMsgs =
-            Executors.newFixedThreadPool(2, groupedThreads("onos/of", "ctrl-msg-stats-%d"));
+            Executors.newCachedThreadPool(groupedThreads("onos/of", "event-outgoing-msg-stats-%d"));
 
     // messagesPendingMastership is used as synchronization variable for
     // all mastership related changes. In this block, mastership (including
@@ -167,14 +167,16 @@
             }
         }
 
-        // listen to outgoing control messages
-        msgs.forEach(m -> {
-            if (m.getType() == OFType.PACKET_OUT ||
-                m.getType() == OFType.FLOW_MOD ||
-                m.getType() == OFType.STATS_REQUEST) {
-                executorMsgs.submit(new OFMessageHandler(dpid, m));
-            }
-        });
+        // listen to outgoing control messages only if listeners are registered
+        if (ofOutgoingMsgListener.size() != 0) {
+            msgs.forEach(m -> {
+                if (m.getType() == OFType.PACKET_OUT ||
+                        m.getType() == OFType.FLOW_MOD ||
+                        m.getType() == OFType.STATS_REQUEST) {
+                    executorMsgs.submit(new OFMessageHandler(dpid, m));
+                }
+            });
+        }
     }
 
     private void sendMsgsOnChannel(List<OFMessage> msgs) {
@@ -332,12 +334,12 @@
 
     @Override
     public void addEventListener(OpenFlowEventListener listener) {
-        ofEventListener.add(listener);
+        ofOutgoingMsgListener.add(listener);
     }
 
     @Override
     public void removeEventListener(OpenFlowEventListener listener) {
-        ofEventListener.remove(listener);
+        ofOutgoingMsgListener.remove(listener);
     }
 
     @Override
@@ -547,7 +549,7 @@
 
         @Override
         public void run() {
-            for (OpenFlowEventListener listener : ofEventListener) {
+            for (OpenFlowEventListener listener : ofOutgoingMsgListener) {
                 listener.handleMessage(dpid, msg);
             }
         }