Add a set of synchronous method for control plane monitor service

Change-Id: Ib060282dfe9a302a6cf88b9679555f4a2e8127a2
diff --git a/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlPlaneMonitorService.java b/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlPlaneMonitorService.java
index da97948..353a947 100644
--- a/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlPlaneMonitorService.java
+++ b/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlPlaneMonitorService.java
@@ -73,6 +73,26 @@
                                                    Optional<DeviceId> deviceId);
 
     /**
+     * Synchronous version of getLoad.
+     * Obtains snapshot of control plane load of a specific device.
+     * The metrics range from control messages and system metrics
+     * (e.g., CPU and memory info).
+     * If the device id is not specified, it returns system metrics, otherwise,
+     * it returns control message stats of the given device.
+     *
+     * @param nodeId   node identifier
+     * @param type     control metric type
+     * @param deviceId device identifier
+     * @return control load snapshot
+     */
+    default ControlLoadSnapshot getLoadSync(NodeId nodeId,
+                                            ControlMetricType type,
+                                            Optional<DeviceId> deviceId) {
+        return Tools.futureGetOrElse(getLoad(nodeId, type, deviceId),
+                TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, null);
+    }
+
+    /**
      * Obtains snapshot of control plane load of a specific resource.
      * The metrics include I/O device metrics (e.g., disk and network metrics).
      *
@@ -86,6 +106,23 @@
                                                    String resourceName);
 
     /**
+     * Synchronous version of getLoad.
+     * Obtains snapshot of control plane load of a specific resource.
+     * The metrics include I/O device metrics (e.g., disk and network metrics).
+     *
+     * @param nodeId       node identifier
+     * @param type         control metric type
+     * @param resourceName resource name
+     * @return control load snapshot
+     */
+    default ControlLoadSnapshot getLoadSync(NodeId nodeId,
+                                            ControlMetricType type,
+                                            String resourceName) {
+        return Tools.futureGetOrElse(getLoad(nodeId, type, resourceName),
+                TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, null);
+    }
+
+    /**
      * Obtains snapshot of control plane load of a specific device with the
      * projected range.
      *
@@ -102,6 +139,26 @@
                                                    Optional<DeviceId> deviceId);
 
     /**
+     * Synchronous version of getLoad.
+     * Obtains snapshot of control plane load of a specific device with the
+     * projected range.
+     *
+     * @param nodeId   node identifier
+     * @param type     control metric type
+     * @param duration projected duration
+     * @param unit     projected time unit
+     * @param deviceId device identifier
+     * @return control load snapshot
+     */
+    default ControlLoadSnapshot getLoadSync(NodeId nodeId,
+                                            ControlMetricType type,
+                                            int duration, TimeUnit unit,
+                                            Optional<DeviceId> deviceId) {
+        return Tools.futureGetOrElse(getLoad(nodeId, type, duration, unit, deviceId),
+                TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, null);
+    }
+
+    /**
      * Obtains snapshot of control plane load of a specific resource with the
      * projected range.
      *
@@ -118,6 +175,26 @@
                                                    String resourceName);
 
     /**
+     * Synchronous version of getLoad.
+     * Obtains snapshot of control plane load of a specific resource with the
+     * projected range.
+     *
+     * @param nodeId       node identifier
+     * @param type         control metric type
+     * @param duration     projected duration
+     * @param unit         projected time unit
+     * @param resourceName resource name
+     * @return control load snapshot
+     */
+    default ControlLoadSnapshot getLoadSync(NodeId nodeId,
+                                            ControlMetricType type,
+                                            int duration, TimeUnit unit,
+                                            String resourceName) {
+        return Tools.futureGetOrElse(getLoad(nodeId, type, duration, unit, resourceName),
+                TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, null);
+    }
+
+    /**
      * Obtains a list of names of available resources.
      *
      * @param nodeId       node identifier
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlMetricsStatsListCommand.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlMetricsStatsListCommand.java
index adf65a9..c8ab177 100644
--- a/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlMetricsStatsListCommand.java
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlMetricsStatsListCommand.java
@@ -17,7 +17,6 @@
 
 import org.apache.karaf.shell.commands.Argument;
 import org.apache.karaf.shell.commands.Command;
-import org.onlab.util.Tools;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.cluster.NodeId;
 import org.onosproject.cpman.ControlLoadSnapshot;
@@ -27,8 +26,6 @@
 
 import java.util.Optional;
 import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
 
 import static org.onosproject.cpman.ControlResource.CONTROL_MESSAGE_METRICS;
 import static org.onosproject.cpman.ControlResource.CPU_METRICS;
@@ -47,8 +44,6 @@
             "averageValue=%d, latestTime=%s";
     private static final String INVALID_TYPE = "Invalid control resource type.";
 
-    private static final long TIMEOUT_MILLIS = 3000;
-
     @Argument(index = 0, name = "node", description = "ONOS node identifier",
             required = true, multiValued = false)
     String node = null;
@@ -91,51 +86,80 @@
         }
     }
 
+    /**
+     * Prints system metric statistic information.
+     *
+     * @param service monitor service
+     * @param nodeId  node identifier
+     * @param typeSet control metric type
+     */
     private void printMetricsStats(ControlPlaneMonitorService service, NodeId nodeId,
                                    Set<ControlMetricType> typeSet) {
         printMetricsStats(service, nodeId, typeSet, null, null);
     }
 
+    /**
+     * Prints disk and network metric statistic information.
+     *
+     * @param service monitor service
+     * @param nodeId  node identifier
+     * @param typeSet control metric type
+     * @param resName resource name
+     */
     private void printMetricsStats(ControlPlaneMonitorService service, NodeId nodeId,
                                    Set<ControlMetricType> typeSet, String resName) {
         printMetricsStats(service, nodeId, typeSet, resName, null);
     }
 
+    /**
+     * Prints control message metric statistic information.
+     *
+     * @param service monitor service
+     * @param nodeId  node identifier
+     * @param typeSet control metric type
+     * @param did     device identifier
+     */
     private void printMetricsStats(ControlPlaneMonitorService service, NodeId nodeId,
                                    Set<ControlMetricType> typeSet, DeviceId did) {
         printMetricsStats(service, nodeId, typeSet, null, did);
     }
 
+    /**
+     * Prints control plane metric statistic information.
+     *
+     * @param service monitor service
+     * @param nodeId  node identifier
+     * @param typeSet control metric type
+     * @param resName resource name
+     * @param did     device identifier
+     */
     private void printMetricsStats(ControlPlaneMonitorService service, NodeId nodeId,
                                    Set<ControlMetricType> typeSet, String resName, DeviceId did) {
         if (resName == null && did == null) {
             typeSet.forEach(s -> {
-                CompletableFuture<ControlLoadSnapshot> cf =
-                        service.getLoad(nodeId, s, Optional.empty());
-                ControlLoadSnapshot cmr =
-                        Tools.futureGetOrElse(cf, TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, null);
-                printRemote(s, cmr);
+                ControlLoadSnapshot cls = service.getLoadSync(nodeId, s, Optional.empty());
+                printControlLoadSnapshot(s, cls);
             });
-        } else if (resName == null && did != null) {
+        } else if (resName == null) {
             typeSet.forEach(s -> {
-                CompletableFuture<ControlLoadSnapshot> cf =
-                        service.getLoad(nodeId, s, Optional.of(did));
-                ControlLoadSnapshot cmr =
-                        Tools.futureGetOrElse(cf, TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, null);
-                printRemote(s, cmr);
+                ControlLoadSnapshot cls = service.getLoadSync(nodeId, s, Optional.of(did));
+                printControlLoadSnapshot(s, cls);
             });
-        } else if (resName != null && did == null) {
+        } else if (did == null) {
             typeSet.forEach(s -> {
-                CompletableFuture<ControlLoadSnapshot> cf =
-                        service.getLoad(nodeId, s, resName);
-                ControlLoadSnapshot cmr =
-                        Tools.futureGetOrElse(cf, TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, null);
-                printRemote(s, cmr);
+                ControlLoadSnapshot cls = service.getLoadSync(nodeId, s, resName);
+                printControlLoadSnapshot(s, cls);
             });
         }
     }
 
-    private void printRemote(ControlMetricType cmType, ControlLoadSnapshot cls) {
+    /**
+     * Prints control load snapshot.
+     *
+     * @param cmType control metric type
+     * @param cls    control load snapshot
+     */
+    private void printControlLoadSnapshot(ControlMetricType cmType, ControlLoadSnapshot cls) {
         if (cls != null) {
             print(FMT, cmType.toString(), cls.latest(), cls.average(), cls.time());
         } else {
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/gui/CpmanViewMessageHandler.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/gui/CpmanViewMessageHandler.java
index 22ad36c..a5f220d 100644
--- a/apps/cpman/app/src/main/java/org/onosproject/cpman/gui/CpmanViewMessageHandler.java
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/gui/CpmanViewMessageHandler.java
@@ -149,21 +149,15 @@
                                                               ClusterService cs, DeviceId deviceId) {
             Map<ControlMetricType, Long[]> data = Maps.newHashMap();
             for (ControlMetricType cmt : CONTROL_MESSAGE_METRICS) {
-                ControlLoadSnapshot cls;
-                try {
-                    cls = cpms.getLoad(cs.getLocalNode().id(),
-                            cmt, NUM_OF_DATA_POINTS, TimeUnit.MINUTES,
-                            Optional.of(deviceId)).get();
+                ControlLoadSnapshot cls = cpms.getLoadSync(cs.getLocalNode().id(),
+                        cmt, NUM_OF_DATA_POINTS, TimeUnit.MINUTES, Optional.of(deviceId));
 
-                    // TODO: in some cases, the number of returned dataset is
-                    // less than what we expected (expected -1)
-                    // As a workaround, we simply fill the slot with 0 values,
-                    // such a bug should be fixed with updated RRD4J lib...
-                    data.put(cmt, ArrayUtils.toObject(fillData(cls.recent(), NUM_OF_DATA_POINTS)));
-                    timestamp = cls.time();
-                } catch (InterruptedException | ExecutionException e) {
-                    log.warn(e.getMessage());
-                }
+                // TODO: in some cases, the number of returned data set is
+                // less than what we expected (expected -1)
+                // As a workaround, we simply fill the slot with 0 values,
+                // such a bug should be fixed with updated RRD4J lib...
+                data.put(cmt, ArrayUtils.toObject(fillData(cls.recent(), NUM_OF_DATA_POINTS)));
+                timestamp = cls.time();
             }
             return data;
         }
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/ControlMetricsWebResource.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/ControlMetricsWebResource.java
index b18a6b5..f8af1b0 100644
--- a/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/ControlMetricsWebResource.java
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/ControlMetricsWebResource.java
@@ -18,7 +18,6 @@
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.apache.commons.lang3.StringUtils;
-import org.onlab.util.Tools;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.NodeId;
 import org.onosproject.cpman.ControlLoadSnapshot;
@@ -35,8 +34,6 @@
 import javax.ws.rs.core.Response;
 import java.util.Optional;
 import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
 
 import static org.onosproject.cpman.ControlResource.CONTROL_MESSAGE_METRICS;
 import static org.onosproject.cpman.ControlResource.CPU_METRICS;
@@ -58,7 +55,6 @@
     private final ClusterService clusterService = get(ClusterService.class);
     private final NodeId localNodeId = clusterService.getLocalNode().id();
     private final ObjectNode root = mapper().createObjectNode();
-    private static final long TIMEOUT_MILLIS = 1000;
 
     /**
      * Returns control message metrics of all devices.
@@ -251,59 +247,32 @@
 
         if (name == null && did == null) {
             typeSet.forEach(type -> {
-                ObjectNode metricNode = mapper().createObjectNode();
-                CompletableFuture<ControlLoadSnapshot> cf =
-                        service.getLoad(nodeId, type, Optional.empty());
-
-                if (cf != null) {
-                    ControlLoadSnapshot cmr =
-                            Tools.futureGetOrElse(cf, TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, null);
-
-                    if (cmr != null) {
-                        metricNode.set(toCamelCase(type.toString(), true),
-                                codec(ControlLoadSnapshot.class).encode(cmr, this));
-                        metricsNode.add(metricNode);
-                    }
-                }
+                ControlLoadSnapshot cls = service.getLoadSync(nodeId, type, Optional.empty());
+                processRest(cls, type, metricsNode);
             });
         } else if (name == null) {
             typeSet.forEach(type -> {
-                ObjectNode metricNode = mapper().createObjectNode();
-                CompletableFuture<ControlLoadSnapshot> cf =
-                        service.getLoad(nodeId, type, Optional.of(did));
-
-                if (cf != null) {
-                    ControlLoadSnapshot cmr =
-                            Tools.futureGetOrElse(cf, TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, null);
-                    if (cmr != null) {
-                        metricNode.set(toCamelCase(type.toString(), true),
-                                codec(ControlLoadSnapshot.class).encode(cmr, this));
-                        metricsNode.add(metricNode);
-                    }
-                }
-
+                ControlLoadSnapshot cls = service.getLoadSync(nodeId, type, Optional.of(did));
+                processRest(cls, type, metricsNode);
             });
         } else if (did == null) {
             typeSet.forEach(type -> {
-                ObjectNode metricNode = mapper().createObjectNode();
-                CompletableFuture<ControlLoadSnapshot> cf =
-                        service.getLoad(nodeId, type, name);
-
-                if (cf != null) {
-                    ControlLoadSnapshot cmr =
-                            Tools.futureGetOrElse(cf, TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, null);
-                    if (cmr != null) {
-                        metricNode.set(toCamelCase(type.toString(), true),
-                                codec(ControlLoadSnapshot.class).encode(cmr, this));
-                        metricsNode.add(metricNode);
-                    }
-                }
+                ControlLoadSnapshot cls = service.getLoadSync(nodeId, type, name);
+                processRest(cls, type, metricsNode);
             });
         }
 
         return metricsNode;
     }
 
+    /**
+     * Camelizes the input string.
+     *
+     * @param value              original string
+     * @param startWithLowerCase flag that determines whether to use lower case
+     *                           for the camelized string
+     * @return camelized string
+     */
     private String toCamelCase(String value, boolean startWithLowerCase) {
         String[] strings = StringUtils.split(value.toLowerCase(), "_");
         for (int i = startWithLowerCase ? 1 : 0; i < strings.length; i++) {
@@ -311,4 +280,21 @@
         }
         return StringUtils.join(strings);
     }
+
+    /**
+     * Transforms control load snapshot object into JSON object.
+     *
+     * @param cls         control load snapshot
+     * @param type        control metric type
+     * @param metricsNode array of JSON node
+     */
+    private void processRest(ControlLoadSnapshot cls, ControlMetricType type, ArrayNode metricsNode) {
+        ObjectNode metricNode = mapper().createObjectNode();
+
+        if (cls != null) {
+            metricNode.set(toCamelCase(type.toString(), true),
+                    codec(ControlLoadSnapshot.class).encode(cls, this));
+            metricsNode.add(metricNode);
+        }
+    }
 }
diff --git a/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsResourceTest.java b/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsResourceTest.java
index 24f659b..ac1ea27 100644
--- a/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsResourceTest.java
+++ b/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsResourceTest.java
@@ -183,7 +183,7 @@
     public void testResourcePopulatedArray() {
         expect(mockControlPlaneMonitorService.availableResourcesSync(anyObject(), anyObject()))
                 .andReturn(resourceSet).once();
-        expect(mockControlPlaneMonitorService.getLoad(anyObject(), anyObject(),
+        expect(mockControlPlaneMonitorService.getLoadSync(anyObject(), anyObject(),
                 anyString())).andReturn(null).times(4);
         replay(mockControlPlaneMonitorService);