changeset 266:aa3fb04ae01f

Avoid negative value results when computing cpu usage Reviewed-by: vanaltj Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-April/001086.html
author Omair Majid <omajid@redhat.com>
date Thu, 26 Apr 2012 13:32:33 -0400
parents 70acf0d10ec2
children 7d5c9fdb7305
files agent/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilder.java agent/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java agent/src/main/java/com/redhat/thermostat/backend/system/VmCpuStatBuilder.java agent/src/test/java/com/redhat/thermostat/backend/system/VmCpuStatBuilderTest.java
diffstat 4 files changed, 37 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilder.java	Thu Apr 26 13:29:37 2012 -0400
+++ b/agent/src/main/java/com/redhat/thermostat/backend/system/ProcessStatusInfoBuilder.java	Thu Apr 26 13:32:33 2012 -0400
@@ -68,7 +68,7 @@
             logger.log(Level.WARNING, "unable to read stat info for " + pid);
         }
 
-        return new ProcessStatusInfo(-1, -1, -1);
+        return null;
     }
 
     private ProcessStatusInfo build(Reader r) throws IOException {
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java	Thu Apr 26 13:29:37 2012 -0400
+++ b/agent/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java	Thu Apr 26 13:32:33 2012 -0400
@@ -67,6 +67,7 @@
 import com.redhat.thermostat.common.dao.VmInfoDAO;
 import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
 import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
+import com.redhat.thermostat.common.model.VmCpuStat;
 import com.redhat.thermostat.common.storage.Category;
 import com.redhat.thermostat.common.utils.LoggingUtils;
 
@@ -161,7 +162,10 @@
 
                 for (Integer pid : pidsToMonitor) {
                     if (vmCpuBuilder.knowsAbout(pid)) {
-                        vmCpuStats.putVmCpuStat(vmCpuBuilder.build(pid));
+                        VmCpuStat dataBuilt = vmCpuBuilder.build(pid);
+                        if (dataBuilt != null) {
+                            vmCpuStats.putVmCpuStat(dataBuilt);
+                        }
                     } else {
                         vmCpuBuilder.learnAbout(pid);
                     }
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/VmCpuStatBuilder.java	Thu Apr 26 13:29:37 2012 -0400
+++ b/agent/src/main/java/com/redhat/thermostat/backend/system/VmCpuStatBuilder.java	Thu Apr 26 13:32:33 2012 -0400
@@ -67,12 +67,9 @@
     }
 
     /**
-     * To build the stat, this method needs to be called repeatedly. The first
-     * time (in the entire run time) it is called, the result will most be
-     * useless. The second (and later calls) should produce usable results.
-     *
-     * @param pid
-     * @return
+     * @param pid the process id
+     * @return an object representing the cpu usage of the process, or null if
+     * the information can not be found.
      */
     public synchronized VmCpuStat build(Integer pid) {
         if (!lastProcessTicks.containsKey(pid) || !lastProcessTickTime.containsKey(pid)) {
@@ -80,6 +77,9 @@
         }
 
         ProcessStatusInfo info = statusBuilder.build(pid);
+        if (info == null) {
+            return null;
+        }
         long miliTime = clock.getRealTimeMillis();
         long time = clock.getMonotonicTimeNanos();
         long programTicks = (info.getKernelTime() + info.getUserTime());
@@ -113,6 +113,9 @@
     public synchronized void learnAbout(int pid) {
         long time = clock.getMonotonicTimeNanos();
         ProcessStatusInfo info = statusBuilder.build(pid);
+        if (info == null) {
+            logger.log(Level.WARNING, "can not learn about pid " + pid + " : statusBuilder returned null");
+        }
 
         lastProcessTickTime.put(pid, time);
         lastProcessTicks.put(pid, info.getUserTime()+ info.getKernelTime());
--- a/agent/src/test/java/com/redhat/thermostat/backend/system/VmCpuStatBuilderTest.java	Thu Apr 26 13:29:37 2012 -0400
+++ b/agent/src/test/java/com/redhat/thermostat/backend/system/VmCpuStatBuilderTest.java	Thu Apr 26 13:32:33 2012 -0400
@@ -76,6 +76,28 @@
     }
 
     @Test
+    public void testBuildNullOnInsufficentInformation() {
+        int PID = 0;
+        int cpuCount = 0;
+        long ticksPerSecond = 0;
+        final long CLOCK1 = 10000;
+        final long CLOCK2 = 20000;
+        final ProcessStatusInfo initialInfo = new ProcessStatusInfo(PID, 1, 2);
+        final ProcessStatusInfo laterInfo = null;
+
+        Clock clock = mock(Clock.class);
+        when(clock.getMonotonicTimeNanos()).thenReturn((long) (CLOCK1 * 1E6)).thenReturn((long) (CLOCK2 * 1E6));
+
+        ProcessStatusInfoBuilder statusBuilder = mock(ProcessStatusInfoBuilder.class);
+        when(statusBuilder.build(any(Integer.class))).thenReturn(initialInfo).thenReturn(laterInfo).thenReturn(null);
+
+        VmCpuStatBuilder builder = new VmCpuStatBuilder(clock, cpuCount, ticksPerSecond, statusBuilder);
+
+        builder.learnAbout(PID);
+        assertEquals(null, builder.build(PID));
+    }
+
+    @Test
     public void testSaneBuild() {
         final int PID = 0;