changeset 392:809924b921ec

Implement histogram support. Reviewed-by: neugens Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-June/001898.html PR 1032
author Roman Kennke <rkennke@redhat.com>
date Tue, 19 Jun 2012 19:44:05 +0200
parents 7a5ea4137f04
children cb22cde2bd47
files client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumperCommand.java common/core/src/main/java/com/redhat/thermostat/common/dao/HeapDAO.java common/core/src/main/java/com/redhat/thermostat/common/dao/HeapDAOImpl.java common/core/src/main/java/com/redhat/thermostat/common/model/HeapInfo.java common/core/src/test/java/com/redhat/thermostat/common/dao/HeapDAOTest.java common/core/src/test/java/com/redhat/thermostat/common/model/HeapInfoTest.java
diffstat 6 files changed, 86 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumperCommand.java	Tue Jun 19 19:11:24 2012 +0200
+++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumperCommand.java	Tue Jun 19 19:44:05 2012 +0200
@@ -40,6 +40,7 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.InputStream;
 import java.nio.file.Files;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -56,19 +57,9 @@
     public HeapDump execute(VmRef reference) {
 
         try {
-            File tempFile = Files.createTempFile("thermostat-", "-heapdump").toFile();
-            String tempFileName = tempFile.getAbsolutePath();
-            tempFile.delete(); // Need to delete before dumping heap, jmap does not override existing file and stop with an error.
-            Process proc = Runtime.getRuntime().exec(new String[] {"jmap", "-dump:format=b,file=" + tempFileName, reference.getIdString()});
-            try {
-                proc.waitFor();
-                log.info("Heap dump written to: " + tempFileName);
-            
-            } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
-            }
-
-            HeapInfo info = saveHeapDumpInfo(reference, tempFile);
+            File heapDumpFile = dumpHeap(reference);
+            InputStream histogram = writeHistogram(reference);
+            HeapInfo info = saveHeapDumpInfo(reference, heapDumpFile, histogram);
             
             HeapDump dump = new HeapDump();
             dump.setHeapInfo(info);
@@ -81,14 +72,35 @@
             return null;
         }
     }
+
+    private File dumpHeap(VmRef reference) throws IOException {
+        File tempFile = Files.createTempFile("thermostat-", "-heapdump").toFile();
+        String tempFileName = tempFile.getAbsolutePath();
+        tempFile.delete(); // Need to delete before dumping heap, jmap does not override existing file and stop with an error.
+        Process proc = Runtime.getRuntime().exec(new String[] {"jmap", "-dump:format=b,file=" + tempFileName, reference.getIdString()});
+        try {
+            proc.waitFor();
+            log.info("Heap dump written to: " + tempFileName);
+        
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+        }
+        return tempFile;
+    }
     
-    private HeapInfo saveHeapDumpInfo(VmRef reference, File tempFile) throws FileNotFoundException {
+    private InputStream writeHistogram(VmRef reference) throws IOException {
+        Process proc = Runtime.getRuntime().exec(new String[] {"jmap", "-histo", reference.getIdString()});
+        InputStream histogramStream = proc.getInputStream();
+        return histogramStream;
+    }
+
+    private HeapInfo saveHeapDumpInfo(VmRef reference, File tempFile, InputStream histogram) throws FileNotFoundException {
     
         HeapDAO heapDAO = ApplicationContext.getInstance().getDAOFactory().getHeapDAO();
         HeapInfo heapInfo = new HeapInfo(reference, System.currentTimeMillis());
         heapInfo.setHeapDumpId(reference.getStringID() + "-" + reference.getAgent().getAgentId() + "-" + heapInfo.getTimestamp());
         
-        heapDAO.putHeapInfo(heapInfo, new FileInputStream(tempFile));
+        heapDAO.putHeapInfo(heapInfo, new FileInputStream(tempFile), histogram);
         
         return heapInfo;
     }
--- a/common/core/src/main/java/com/redhat/thermostat/common/dao/HeapDAO.java	Tue Jun 19 19:11:24 2012 +0200
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/HeapDAO.java	Tue Jun 19 19:44:05 2012 +0200
@@ -46,13 +46,16 @@
 public interface HeapDAO {
 
     static final Key<String> heapDumpIdKey = new Key<String>("heap-dump-id", false);
+    static final Key<String> histogramIdKey = new Key<String>("histogram-id", false);
 
-    public static final Category heapInfoCategory = new Category("vm-heap-info", Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, heapDumpIdKey);
+    public static final Category heapInfoCategory = new Category("vm-heap-info", Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, heapDumpIdKey, histogramIdKey);
 
-    void putHeapInfo(HeapInfo heapInfo, InputStream heapDump);
+    void putHeapInfo(HeapInfo heapInfo, InputStream heapDump, InputStream histogramData);
 
     Collection<HeapInfo> getAllHeapInfo(VmRef vm);
 
     InputStream getHeapDump(HeapInfo heapInfo);
 
+    InputStream getHistogram(HeapInfo heapInfo);
+
 }
--- a/common/core/src/main/java/com/redhat/thermostat/common/dao/HeapDAOImpl.java	Tue Jun 19 19:11:24 2012 +0200
+++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/HeapDAOImpl.java	Tue Jun 19 19:44:05 2012 +0200
@@ -56,7 +56,7 @@
     }
 
     @Override
-    public void putHeapInfo(HeapInfo heapInfo, InputStream heapDumpData) {
+    public void putHeapInfo(HeapInfo heapInfo, InputStream heapDumpData, InputStream histogramData) {
         VmRef vm = heapInfo.getVm();
         Chunk chunk = new Chunk(heapInfoCategory, false);
         
@@ -64,13 +64,20 @@
         chunk.put(Key.VM_ID, vm.getId());
         chunk.put(Key.TIMESTAMP, heapInfo.getTimestamp());
         String heapDumpId = "heapdump-" + vm.getAgent().getStringID() + "-" + vm.getId() + "-" + heapInfo.getTimestamp();
+        String histogramId = "histogram-" + vm.getAgent().getStringID() + "-" + vm.getId() + "-" + heapInfo.getTimestamp();
         if (heapDumpData != null) {
             chunk.put(heapDumpIdKey, heapDumpId);
         }
+        if (histogramData != null) {
+            chunk.put(histogramIdKey, histogramId);
+        }
         storage.putChunk(chunk);
         if (heapDumpData != null) {
             storage.saveFile(heapDumpId, heapDumpData);
         }
+        if (histogramData != null) {
+            storage.saveFile(histogramId, histogramData);
+        }
     }
 
     @Override
@@ -98,4 +105,9 @@
         return storage.loadFile(heapInfo.getHeapDumpId());
     }
 
+    @Override
+    public InputStream getHistogram(HeapInfo heapInfo) {
+        return storage.loadFile(heapInfo.getHistogramId());
+    }
+
 }
--- a/common/core/src/main/java/com/redhat/thermostat/common/model/HeapInfo.java	Tue Jun 19 19:11:24 2012 +0200
+++ b/common/core/src/main/java/com/redhat/thermostat/common/model/HeapInfo.java	Tue Jun 19 19:44:05 2012 +0200
@@ -45,6 +45,7 @@
     private VmRef vm;
     private long timestamp;
     private String heapDumpId;
+    private String histogramId;
 
     public HeapInfo(VmRef vm, long timestamp) {
         this.vm = vm;
@@ -73,11 +74,20 @@
             return false;
         }
         HeapInfo other = (HeapInfo) o;
-        return Objects.equals(vm, other.vm) && Objects.equals(heapDumpId, other.heapDumpId) && timestamp == other.timestamp;
+        return Objects.equals(vm, other.vm) && Objects.equals(heapDumpId, other.heapDumpId)
+               && Objects.equals(histogramId, other.histogramId) && timestamp == other.timestamp;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(vm, heapDumpId, timestamp);
+        return Objects.hash(vm, heapDumpId, histogramId, timestamp);
+    }
+
+    public String getHistogramId() {
+        return histogramId;
+    }
+
+    public void setHistogramId(String histogramId) {
+        this.histogramId = histogramId;
     }
 }
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/HeapDAOTest.java	Tue Jun 19 19:11:24 2012 +0200
+++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/HeapDAOTest.java	Tue Jun 19 19:44:05 2012 +0200
@@ -71,6 +71,7 @@
     private Storage storage;
     private HeapInfo heapInfo;
     private InputStream heapDumpData;
+    private InputStream histogramData;
 
     @Before
     public void setUp() {
@@ -82,6 +83,8 @@
         heapInfo = new HeapInfo(vm, 12345);
         byte[] data = new byte[] { 1, 2, 3 };
         heapDumpData = new ByteArrayInputStream(data);
+        data = new byte[] { 4, 5, 6 };
+        histogramData = new ByteArrayInputStream(data);
 
         // Setup for reading data from DB.
         Chunk findAllQuery = new Chunk(HeapDAO.heapInfoCategory, false);
@@ -103,7 +106,8 @@
         when(storage.findAll(findAllQuery)).thenReturn(cursor);
 
         // Setup for reading heapdump data.
-        when(storage.loadFile("test")).thenReturn(heapDumpData);
+        when(storage.loadFile("test-heap")).thenReturn(heapDumpData);
+        when(storage.loadFile("test-histo")).thenReturn(histogramData);
     }
 
     @After
@@ -120,29 +124,32 @@
         assertNotNull(category);
         assertEquals("vm-heap-info", category.getName());
         Collection<Key<?>> keys = category.getKeys();
-        assertEquals(4, keys.size());
+        assertEquals(5, keys.size());
         assertTrue(keys.contains(new Key<>("agent-id", false)));
         assertTrue(keys.contains(new Key<>("vm-id", false)));
         assertTrue(keys.contains(new Key<>("timestamp", false)));
         assertTrue(keys.contains(new Key<>("heap-dump-id", false)));
+        assertTrue(keys.contains(new Key<>("histogram-id", false)));
     }
 
     @Test
     public void testPutHeapInfo() {
-        dao.putHeapInfo(heapInfo, heapDumpData);
+        dao.putHeapInfo(heapInfo, heapDumpData, histogramData);
 
         Chunk expectedChunk = new Chunk(HeapDAO.heapInfoCategory, false);
         expectedChunk.put(Key.AGENT_ID, "987");
         expectedChunk.put(Key.VM_ID, 123);
         expectedChunk.put(Key.TIMESTAMP, 12345L);
         expectedChunk.put(HeapDAO.heapDumpIdKey, "heapdump-987-123-12345");
+        expectedChunk.put(HeapDAO.histogramIdKey, "histogram-987-123-12345");
         verify(storage).putChunk(expectedChunk);
         verify(storage).saveFile(eq("heapdump-987-123-12345"), same(heapDumpData));
+        verify(storage).saveFile(eq("histogram-987-123-12345"), same(histogramData));
     }
 
     @Test
     public void testPutHeapInfoWithoutDump() {
-        dao.putHeapInfo(heapInfo, null);
+        dao.putHeapInfo(heapInfo, null, null);
 
         Chunk expectedChunk = new Chunk(HeapDAO.heapInfoCategory, false);
         expectedChunk.put(Key.AGENT_ID, "987");
@@ -174,11 +181,21 @@
 
     @Test
     public void testGetHeapDump() throws IOException {
-        heapInfo.setHeapDumpId("test");
+        heapInfo.setHeapDumpId("test-heap");
         InputStream in = dao.getHeapDump(heapInfo);
         assertEquals(1, in.read());
         assertEquals(2, in.read());
         assertEquals(3, in.read());
         assertEquals(-1, in.read());
     }
+
+    @Test
+    public void testGetHistogram() throws IOException {
+        heapInfo.setHistogramId("test-histo");
+        InputStream in = dao.getHistogram(heapInfo);
+        assertEquals(4, in.read());
+        assertEquals(5, in.read());
+        assertEquals(6, in.read());
+        assertEquals(-1, in.read());
+    }
 }
--- a/common/core/src/test/java/com/redhat/thermostat/common/model/HeapInfoTest.java	Tue Jun 19 19:11:24 2012 +0200
+++ b/common/core/src/test/java/com/redhat/thermostat/common/model/HeapInfoTest.java	Tue Jun 19 19:44:05 2012 +0200
@@ -70,4 +70,11 @@
         heapInfo.setHeapDumpId("test");
         assertEquals("test", heapInfo.getHeapDumpId());
     }
+
+    @Test
+    public void testHistogramId() {
+        assertNull(heapInfo.getHistogramId());
+        heapInfo.setHistogramId("test");
+        assertEquals("test", heapInfo.getHistogramId());
+    }
 }