ONOS-6653
provide an option in ONOS to configure Groupstats collection interval
Change-Id: Ia214ff9eed8fa061916f6973dc201cceb0496c71
diff --git a/providers/openflow/group/BUCK b/providers/openflow/group/BUCK
index e76cb53..c6a6f6d 100644
--- a/providers/openflow/group/BUCK
+++ b/providers/openflow/group/BUCK
@@ -5,6 +5,11 @@
     '//providers/openflow/flow:onos-providers-openflow-flow',
 ]
 
+TEST_DEPS = [
+    '//lib:TEST_ADAPTERS',
+]
+
 osgi_jar_with_tests (
     deps = COMPILE_DEPS,
+    test_deps = TEST_DEPS,
 )
diff --git a/providers/openflow/group/pom.xml b/providers/openflow/group/pom.xml
index e958e93..9108883 100644
--- a/providers/openflow/group/pom.xml
+++ b/providers/openflow/group/pom.xml
@@ -36,6 +36,10 @@
             <artifactId>onos-providers-openflow-flow</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+        </dependency>
     </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupStatsCollector.java b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupStatsCollector.java
index 009ce8a..5433a4d 100644
--- a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupStatsCollector.java
+++ b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupStatsCollector.java
@@ -38,7 +38,7 @@
 
     private final OpenFlowSwitch sw;
     private final Logger log = getLogger(getClass());
-    private final int refreshInterval;
+    private int refreshInterval;
 
     private Timeout timeout;
 
@@ -94,6 +94,10 @@
         sw.sendMsg(descStatsRequest);
     }
 
+    public void adjustRate(int pollInterval) {
+        this.refreshInterval = pollInterval;
+    }
+
     /**
      * Starts the collector.
      */
diff --git a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
index bf4a5fd..b536fda 100644
--- a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
+++ b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
@@ -16,21 +16,27 @@
 
 package org.onosproject.provider.of.group.impl;
 
+import static org.onlab.util.Tools.getIntegerProperty;
 import static org.slf4j.LoggerFactory.getLogger;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Dictionary;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Properties;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
@@ -57,6 +63,7 @@
 import org.onosproject.openflow.controller.OpenFlowSwitch;
 import org.onosproject.openflow.controller.OpenFlowSwitchListener;
 import org.onosproject.openflow.controller.RoleState;
+import org.osgi.service.component.ComponentContext;
 import org.projectfloodlight.openflow.protocol.OFBucketCounter;
 import org.projectfloodlight.openflow.protocol.OFErrorMsg;
 import org.projectfloodlight.openflow.protocol.OFErrorType;
@@ -101,9 +108,18 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected GroupService groupService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ComponentConfigService cfgService;
+
     private GroupProviderService providerService;
 
-    static final int POLL_INTERVAL = 10;
+    private static final int DEFAULT_POLL_INTERVAL = 10;
+    private static final String COMPONENT = "org.onosproject.provider.of.group.impl.OpenFlowGroupProvider";
+    private static final String GROUP_POLL_INTERVAL_CONST = "groupPollInterval";
+
+    @Property(name = "groupPollInterval", intValue = DEFAULT_POLL_INTERVAL,
+            label = "Frequency (in seconds) for polling group statistics")
+    private int groupPollInterval = DEFAULT_POLL_INTERVAL;
 
     private final InternalGroupProvider listener = new InternalGroupProvider();
 
@@ -124,14 +140,17 @@
     }
 
     @Activate
-    public void activate() {
+    public void activate(ComponentContext context) {
+        cfgService.registerProperties(getClass());
         providerService = providerRegistry.register(this);
         controller.addListener(listener);
         controller.addEventListener(listener);
 
+        modified(context);
+
         for (OpenFlowSwitch sw : controller.getSwitches()) {
             if (isGroupSupported(sw)) {
-                GroupStatsCollector gsc = new GroupStatsCollector(sw, POLL_INTERVAL);
+                GroupStatsCollector gsc = new GroupStatsCollector(sw, groupPollInterval);
                 gsc.start();
                 collectors.put(new Dpid(sw.getId()), gsc);
             }
@@ -142,6 +161,7 @@
 
     @Deactivate
     public void deactivate() {
+        cfgService.unregisterProperties(getClass(), false);
         providerRegistry.unregister(this);
         providerService = null;
         collectors.values().forEach(GroupStatsCollector::stop);
@@ -149,6 +169,25 @@
         log.info("Stopped");
     }
 
+    @Modified
+    public void modified(ComponentContext context) {
+        Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
+        Integer newGroupPollInterval = getIntegerProperty(properties, GROUP_POLL_INTERVAL_CONST);
+        if (newGroupPollInterval != null && newGroupPollInterval > 0
+                && newGroupPollInterval != groupPollInterval) {
+            groupPollInterval = newGroupPollInterval;
+            modifyPollInterval();
+        } else if (newGroupPollInterval != null && newGroupPollInterval <= 0) {
+            log.warn("groupPollInterval must be greater than 0");
+            //If the new value <= 0 reset property with old value.
+            cfgService.setProperty(COMPONENT, GROUP_POLL_INTERVAL_CONST, Integer.toString(groupPollInterval));
+        }
+    }
+
+    private void modifyPollInterval() {
+        collectors.values().forEach(gsc -> gsc.adjustRate(groupPollInterval));
+
+    }
     @Override
     public void performGroupOperation(DeviceId deviceId, GroupOperations groupOps) {
         final Dpid dpid = Dpid.dpid(deviceId.uri());
@@ -374,7 +413,7 @@
                 return;
             }
             if (isGroupSupported(sw)) {
-                GroupStatsCollector gsc = new GroupStatsCollector(sw, POLL_INTERVAL);
+                GroupStatsCollector gsc = new GroupStatsCollector(sw, groupPollInterval);
                 stopCollectorIfNeeded(collectors.put(dpid, gsc));
                 gsc.start();
             }
diff --git a/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java b/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java
index 78eba35..0b95f1d 100644
--- a/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java
+++ b/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java
@@ -19,6 +19,7 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.onosproject.cfg.ComponentConfigAdapter;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
@@ -80,7 +81,8 @@
     public void setUp() {
         provider.controller = controller;
         provider.providerRegistry = providerRegistry;
-        provider.activate();
+        provider.cfgService = new ComponentConfigAdapter();
+        provider.activate(null);
     }
 
     @Test