Mercurial > hg > release > thermostat-1.0
changeset 378:19a83468b64f
Initial HeapDAO implementation.
Reviewed-by: neugens
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-June/001854.html
PR 1032
line wrap: on
line diff
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpAction.java Wed Jun 13 21:34:41 2012 +0200 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpAction.java Mon Jun 18 16:14:07 2012 +0200 @@ -37,6 +37,8 @@ package com.redhat.thermostat.client.heap; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; import java.util.logging.Level; @@ -45,8 +47,10 @@ import com.redhat.thermostat.client.osgi.service.Filter; import com.redhat.thermostat.client.osgi.service.VMContextAction; import com.redhat.thermostat.common.dao.DAOFactory; +import com.redhat.thermostat.common.dao.HeapDAO; import com.redhat.thermostat.common.dao.Ref; import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.common.model.HeapInfo; import com.redhat.thermostat.common.model.VmInfo; /**
--- a/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java Wed Jun 13 21:34:41 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java Mon Jun 18 16:14:07 2012 +0200 @@ -64,4 +64,6 @@ public VmGcStatDAO getVmGcStatDAO(); + public HeapDAO getHeapDAO(); + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/HeapDAO.java Mon Jun 18 16:14:07 2012 +0200 @@ -0,0 +1,15 @@ +package com.redhat.thermostat.common.dao; + +import com.redhat.thermostat.common.model.HeapInfo; +import com.redhat.thermostat.common.storage.Category; +import com.redhat.thermostat.common.storage.Key; + +public interface HeapDAO { + + static final Key<String> heapDumpIdKey = new Key<String>("heap-dump-id", false); + + public static final Category heapInfoCategory = new Category("vm-heap-info", Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, heapDumpIdKey); + + void putHeapInfo(HeapInfo heapInfo); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/HeapDAOImpl.java Mon Jun 18 16:14:07 2012 +0200 @@ -0,0 +1,38 @@ +package com.redhat.thermostat.common.dao; + +import java.io.InputStream; + +import com.redhat.thermostat.common.model.HeapInfo; +import com.redhat.thermostat.common.storage.Chunk; +import com.redhat.thermostat.common.storage.Key; +import com.redhat.thermostat.common.storage.Storage; + +class HeapDAOImpl implements HeapDAO { + + private Storage storage; + + HeapDAOImpl(Storage storage) { + this.storage = storage; + } + + @Override + public void putHeapInfo(HeapInfo heapInfo) { + VmRef vm = heapInfo.getVm(); + Chunk chunk = new Chunk(heapInfoCategory, false); + + chunk.put(Key.AGENT_ID, vm.getAgent().getStringID()); + chunk.put(Key.VM_ID, vm.getId()); + chunk.put(Key.TIMESTAMP, heapInfo.getTimestamp()); + InputStream heapDumpData = heapInfo.getHeapDump(); + String heapDumpId = "heapdump-" + vm.getAgent().getStringID() + "-" + vm.getId() + "-" + heapInfo.getTimestamp(); + if (heapDumpData != null) { + chunk.put(heapDumpIdKey, heapDumpId); + } + storage.createConnectionKey(heapInfoCategory); + storage.putChunk(chunk); + if (heapDumpData != null) { + storage.saveFile(heapDumpId, heapDumpData); + } + } + +}
--- a/common/core/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java Wed Jun 13 21:34:41 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java Mon Jun 18 16:14:07 2012 +0200 @@ -116,4 +116,10 @@ throw new IllegalStateException("Set up connection before accessing DAO"); } } + + @Override + public HeapDAO getHeapDAO() { + ensureStorageConnected(); + return new HeapDAOImpl(storage); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/common/model/HeapInfo.java Mon Jun 18 16:14:07 2012 +0200 @@ -0,0 +1,33 @@ +package com.redhat.thermostat.common.model; + +import java.io.InputStream; + +import com.redhat.thermostat.common.dao.VmRef; + +public class HeapInfo { + + private VmRef vm; + private long timestamp; + private InputStream heapDump; + + public HeapInfo(VmRef vm, long timestamp) { + this.vm = vm; + this.timestamp = timestamp; + } + + public VmRef getVm() { + return vm; + } + + public long getTimestamp() { + return timestamp; + } + + public InputStream getHeapDump() { + return heapDump; + } + + public void setHeapDump(InputStream heapDump) { + this.heapDump = heapDump; + } +}
--- a/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java Wed Jun 13 21:34:41 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/MongoStorage.java Mon Jun 18 16:14:07 2012 +0200 @@ -36,6 +36,7 @@ package com.redhat.thermostat.common.storage; +import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -50,6 +51,8 @@ import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.WriteConcern; +import com.mongodb.gridfs.GridFS; +import com.mongodb.gridfs.GridFSInputFile; import com.redhat.thermostat.common.config.StartupConfiguration; import com.redhat.thermostat.common.storage.Connection.ConnectionListener; import com.redhat.thermostat.common.storage.Connection.ConnectionStatus; @@ -101,17 +104,27 @@ return new BasicDBObject(KEY_AGENT_ID, agentId.toString()); } + private BasicDBObject getAgentDBObject(Chunk chunk) { + if (agentId != null) { + return getAgentDBObject(); + } else if (chunk.get(Key.AGENT_ID) != null) { + return new BasicDBObject(KEY_AGENT_ID, chunk.get(Key.AGENT_ID)); + } else { + return null; + } + } + @Override public void putChunk(Chunk chunk) { Category cat = chunk.getCategory(); DBCollection coll = getCachedCollection(cat.getName()); - BasicDBObject toInsert = getAgentDBObject(); + BasicDBObject toInsert = getAgentDBObject(chunk); BasicDBObject replaceKey = null; boolean replace = chunk.getReplace(); Map<String, BasicDBObject> nestedParts = new HashMap<String, BasicDBObject>(); Map<String, BasicDBObject> replaceKeyNestedParts = null; if (replace) { - replaceKey = getAgentDBObject(); + replaceKey = getAgentDBObject(chunk); replaceKeyNestedParts = new HashMap<String, BasicDBObject>(); } for (Key<?> key : cat.getKeys()) { @@ -167,7 +180,7 @@ Category cat = chunk.getCategory(); DBCollection coll = getCachedCollection(cat.getName()); BasicDBObject toUpdate = new BasicDBObject(); - BasicDBObject updateKey = getAgentDBObject(); + BasicDBObject updateKey = getAgentDBObject(chunk); Map<String, BasicDBObject> nestedParts = new HashMap<String, BasicDBObject>(); Map<String, BasicDBObject> updateKeyNestedParts = new HashMap<String, BasicDBObject>(); for (Key<?> key : cat.getKeys()) { @@ -368,4 +381,11 @@ } return null; } + + @Override + public void saveFile(String filename, InputStream data) { + GridFS gridFS = new GridFS(db); + GridFSInputFile inputFile = gridFS.createFile(data, filename); + inputFile.save(); + } }
--- a/common/core/src/main/java/com/redhat/thermostat/common/storage/Storage.java Wed Jun 13 21:34:41 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/storage/Storage.java Mon Jun 18 16:14:07 2012 +0200 @@ -36,6 +36,8 @@ package com.redhat.thermostat.common.storage; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.util.UUID; @@ -84,4 +86,6 @@ */ public abstract String getBackendConfig(String backendName, String configurationKey); + public abstract void saveFile(String filename, InputStream data); + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/HeapDAOTest.java Mon Jun 18 16:14:07 2012 +0200 @@ -0,0 +1,92 @@ +package com.redhat.thermostat.common.dao; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.*; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Collection; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.model.HeapInfo; +import com.redhat.thermostat.common.storage.Category; +import com.redhat.thermostat.common.storage.Chunk; +import com.redhat.thermostat.common.storage.Key; +import com.redhat.thermostat.common.storage.Storage; + + +public class HeapDAOTest { + + private HeapDAO dao; + private Storage storage; + private HeapInfo heapInfo; + private InputStream dataStream; + + @Before + public void setUp() { + storage = mock(Storage.class); + dao = new HeapDAOImpl(storage); + HostRef host = new HostRef("987", "test-host"); + VmRef vm = new VmRef(host, 123, "test-vm"); + heapInfo = new HeapInfo(vm, 12345); + byte[] data = new byte[] { 1, 2, 3 }; + dataStream = new ByteArrayInputStream(data); + heapInfo.setHeapDump(dataStream); + } + + @After + public void tearDown() { + dataStream = null; + heapInfo = null; + dao = null; + storage = null; + } + + @Test + public void testCategory() { + Category category = HeapDAO.heapInfoCategory; + assertNotNull(category); + assertEquals("vm-heap-info", category.getName()); + Collection<Key<?>> keys = category.getKeys(); + assertEquals(4, 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))); + } + + @Test + public void testPutHeapInfo() { + dao.putHeapInfo(heapInfo); + + 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"); + verify(storage).putChunk(expectedChunk); + verify(storage).saveFile(eq("heapdump-987-123-12345"), same(dataStream)); + } + + @Test + public void testPutHeapInfoWithoutDump() { + heapInfo.setHeapDump(null); + dao.putHeapInfo(heapInfo); + + Chunk expectedChunk = new Chunk(HeapDAO.heapInfoCategory, false); + expectedChunk.put(Key.AGENT_ID, "987"); + expectedChunk.put(Key.VM_ID, 123); + expectedChunk.put(Key.TIMESTAMP, 12345L); + + verify(storage).putChunk(expectedChunk); + verify(storage, never()).saveFile(anyString(), any(InputStream.class)); + } +}
--- a/common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java Wed Jun 13 21:34:41 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java Mon Jun 18 16:14:07 2012 +0200 @@ -122,4 +122,10 @@ NetworkInterfaceInfoDAO dao = daoFactory.getNetworkInterfaceInfoDAO(); assertNotNull(dao); } + + @Test + public void testGetHeapDAO() { + HeapDAO dao = daoFactory.getHeapDAO(); + assertNotNull(dao); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/test/java/com/redhat/thermostat/common/model/HeapInfoTest.java Mon Jun 18 16:14:07 2012 +0200 @@ -0,0 +1,45 @@ +package com.redhat.thermostat.common.model; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.dao.HostRef; +import com.redhat.thermostat.common.dao.VmRef; + +public class HeapInfoTest { + + private HeapInfo heapInfo; + private VmRef vm; + + @Before + public void setUp() { + HostRef hostRef = new HostRef("321", "test-host"); + vm = new VmRef(hostRef, 123, "test-vm"); + heapInfo = new HeapInfo(vm, 12345); + } + + @Test + public void testProperties() { + assertSame(vm, heapInfo.getVm()); + assertEquals(12345, heapInfo.getTimestamp()); + } + + @Test + public void testHeapDump() throws IOException { + assertNull(heapInfo.getHeapDump()); + byte[] test = new byte[]{ 1 , 2 ,3 }; + heapInfo.setHeapDump(new ByteArrayInputStream(test)); + InputStream in = heapInfo.getHeapDump(); + assertNotNull(in); + assertEquals(1, in.read()); + assertEquals(2, in.read()); + assertEquals(3, in.read()); + assertEquals(-1, in.read()); + } +}
--- a/common/core/src/test/java/com/redhat/thermostat/common/storage/MongoStorageTest.java Wed Jun 13 21:34:41 2012 +0200 +++ b/common/core/src/test/java/com/redhat/thermostat/common/storage/MongoStorageTest.java Mon Jun 18 16:14:07 2012 +0200 @@ -44,10 +44,15 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.io.ByteArrayInputStream; +import java.io.InputStream; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -64,6 +69,8 @@ import com.mongodb.DBObject; import com.mongodb.Mongo; import com.mongodb.MongoURI; +import com.mongodb.gridfs.GridFS; +import com.mongodb.gridfs.GridFSInputFile; import com.redhat.thermostat.common.config.StartupConfiguration; @RunWith(PowerMockRunner.class) @@ -337,4 +344,19 @@ assertFalse(cursor.hasNext()); assertNull(cursor.next()); } + + @Test + public void verifySaveFile() throws Exception { + GridFSInputFile gridFSFile = mock(GridFSInputFile.class); + GridFS gridFS = mock(GridFS.class); + when(gridFS.createFile(any(InputStream.class), anyString())).thenReturn(gridFSFile); + PowerMockito.whenNew(GridFS.class).withArguments(any()).thenReturn(gridFS); + PowerMockito.whenNew(Mongo.class).withParameterTypes(MongoURI.class).withArguments(any(MongoURI.class)).thenReturn(m); + MongoStorage storage = makeStorage(); + byte[] data = new byte[] { 1, 2, 3 }; + InputStream dataStream = new ByteArrayInputStream(data); + storage.saveFile("test", dataStream); + verify(gridFS).createFile(same(dataStream), eq("test")); + verify(gridFSFile).save(); + } }