# HG changeset patch # User Elliott Baron # Date 1357591859 18000 # Node ID ceb28ef8f9e8f2de33e3821ce00d2d76c968e785 # Parent 0ba74f790a8a91f42fc9188403ff5e32b0b56873 Create VM GC agent and common bundles This commit extracts VM GC data collection from SystemBackend and related classes to a vm-gc-agent bundle. It also moves the VmGcStatDAO from common-core to a vm-gc-common bundle that registers the DAO once Storage is available. This also removes the DAO from DAOFactory. Reviewed-by: omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-January/004997.html diff -r 0ba74f790a8a -r ceb28ef8f9e8 common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java --- a/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java Mon Jan 07 15:50:03 2013 -0500 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java Mon Jan 07 15:50:59 2013 -0500 @@ -58,8 +58,6 @@ public VmClassStatDAO getVmClassStatsDAO(); - public VmGcStatDAO getVmGcStatDAO(); - public void registerDAOsAndStorageAsOSGiServices(); public void unregisterDAOsAndStorageAsOSGiServices(); diff -r 0ba74f790a8a -r ceb28ef8f9e8 common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactoryImpl.java --- a/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactoryImpl.java Mon Jan 07 15:50:03 2013 -0500 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactoryImpl.java Mon Jan 07 15:50:59 2013 -0500 @@ -60,7 +60,6 @@ private NetworkInterfaceInfoDAO networkInfoDAO; private VmInfoDAO vmInfoDAO; private VmClassStatDAO vmClassStatDAO; - private VmGcStatDAO vmGcStatDAO; public DAOFactoryImpl(StorageProvider prov) { this(FrameworkUtil.getBundle(DAOFactoryImpl.class).getBundleContext(), prov); @@ -113,12 +112,6 @@ } @Override - public VmGcStatDAO getVmGcStatDAO() { - ensureStorageConnected(); - return vmGcStatDAO; - } - - @Override public Storage getStorage() { return storage; } @@ -143,7 +136,6 @@ registerAndRecordService(VmInfoDAO.class, getVmInfoDAO()); registerAndRecordService(VmClassStatDAO.class, getVmClassStatsDAO()); - registerAndRecordService(VmGcStatDAO.class, getVmGcStatDAO()); } /* @@ -156,7 +148,6 @@ networkInfoDAO = new NetworkInterfaceInfoDAOImpl(storage); vmInfoDAO = new VmInfoDAOImpl(storage); vmClassStatDAO = new VmClassStatDAOImpl(storage); - vmGcStatDAO = new VmGcStatDAOImpl(storage); } private void registerAndRecordService(Class serviceType, K serviceImplementation) { diff -r 0ba74f790a8a -r ceb28ef8f9e8 common/core/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java --- a/common/core/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java Mon Jan 07 15:50:03 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.common.dao; - -import java.util.List; - -import com.redhat.thermostat.storage.core.Category; -import com.redhat.thermostat.storage.core.Key; -import com.redhat.thermostat.storage.model.VmGcStat; - -public interface VmGcStatDAO { - - static final Key collectorKey = new Key<>("collectorName", false); - static final Key runCountKey = new Key<>("runCount", false); - /** time in microseconds */ - static final Key wallTimeKey = new Key<>("wallTime", false); - - static final Category vmGcStatCategory = new Category("vm-gc-stats", - Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, collectorKey, - runCountKey, wallTimeKey); - - public List getLatestVmGcStats(VmRef ref, long since); - - public void putVmGcStat(VmGcStat stat); -} diff -r 0ba74f790a8a -r ceb28ef8f9e8 common/core/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAOImpl.java --- a/common/core/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAOImpl.java Mon Jan 07 15:50:03 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.common.dao; - -import java.util.List; - -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.model.VmGcStat; - -class VmGcStatDAOImpl implements VmGcStatDAO { - - private final Storage storage; - private final VmLatestPojoListGetter getter; - - VmGcStatDAOImpl(Storage storage) { - this.storage = storage; - storage.registerCategory(vmGcStatCategory); - getter = new VmLatestPojoListGetter<>(storage, vmGcStatCategory, VmGcStat.class); - } - - @Override - public List getLatestVmGcStats(VmRef ref, long since) { - return getter.getLatest(ref, since); - } - - @Override - public void putVmGcStat(VmGcStat stat) { - storage.putPojo(vmGcStatCategory, false, stat); - } - -} diff -r 0ba74f790a8a -r ceb28ef8f9e8 common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java --- a/common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java Mon Jan 07 15:50:03 2013 -0500 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -96,12 +96,6 @@ } @Test - public void testGetVmGcStatDAO() { - VmGcStatDAO dao = daoFactory.getVmGcStatDAO(); - assertNotNull(dao); - } - - @Test public void testGetVmInfoDAO() { VmInfoDAO dao = daoFactory.getVmInfoDAO(); assertNotNull(dao); @@ -125,8 +119,8 @@ daoFactory.registerDAOsAndStorageAsOSGiServices(); - // currently 8 DAOs and Storage are registered - assertEquals(8, bundleContext.getAllServices().size()); + // currently 7 DAOs and Storage are registered + assertEquals(7, bundleContext.getAllServices().size()); } @Test diff -r 0ba74f790a8a -r ceb28ef8f9e8 common/core/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java --- a/common/core/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java Mon Jan 07 15:50:03 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.common.dao; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -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.util.Collection; -import java.util.List; - -import org.junit.Test; -import org.mockito.ArgumentCaptor; - -import com.redhat.thermostat.storage.core.Cursor; -import com.redhat.thermostat.storage.core.Key; -import com.redhat.thermostat.storage.core.Query; -import com.redhat.thermostat.storage.core.Storage; -import com.redhat.thermostat.storage.core.Query.Criteria; -import com.redhat.thermostat.storage.model.VmGcStat; -import com.redhat.thermostat.test.MockQuery; - -public class VmGcStatDAOTest { - - private static final Integer VM_ID = 123; - private static final Long TIMESTAMP = 456L; - private static final String COLLECTOR = "collector1"; - private static final Long RUN_COUNT = 10L; - private static final Long WALL_TIME = 9L; - - @Test - public void testCategory() { - assertEquals("vm-gc-stats", VmGcStatDAO.vmGcStatCategory.getName()); - Collection> keys = VmGcStatDAO.vmGcStatCategory.getKeys(); - assertTrue(keys.contains(new Key<>("agentId", true))); - assertTrue(keys.contains(new Key("vmId", true))); - assertTrue(keys.contains(new Key("timeStamp", false))); - assertTrue(keys.contains(new Key("collectorName", false))); - assertTrue(keys.contains(new Key("runCount", false))); - assertTrue(keys.contains(new Key("wallTime", false))); - assertEquals(6, keys.size()); - } - - @Test - public void testGetLatestVmGcStatsBasic() { - - VmGcStat vmGcStat = new VmGcStat(VM_ID, TIMESTAMP, COLLECTOR, RUN_COUNT, WALL_TIME); - - @SuppressWarnings("unchecked") - Cursor cursor = mock(Cursor.class); - when(cursor.hasNext()).thenReturn(true).thenReturn(false); - when(cursor.next()).thenReturn(vmGcStat); - - Storage storage = mock(Storage.class); - when(storage.createQuery()).thenReturn(new MockQuery()); - when(storage.findAllPojos(any(Query.class), same(VmGcStat.class))).thenReturn(cursor); - - HostRef hostRef = mock(HostRef.class); - when(hostRef.getAgentId()).thenReturn("system"); - - VmRef vmRef = mock(VmRef.class); - when(vmRef.getAgent()).thenReturn(hostRef); - when(vmRef.getId()).thenReturn(321); - - - VmGcStatDAO dao = new VmGcStatDAOImpl(storage); - List vmGcStats = dao.getLatestVmGcStats(vmRef, Long.MIN_VALUE); - - ArgumentCaptor arg = ArgumentCaptor.forClass(MockQuery.class); - verify(storage).findAllPojos(arg.capture(), same(VmGcStat.class)); - assertTrue(arg.getValue().hasWhereClause(Key.TIMESTAMP, Criteria.GREATER_THAN, Long.MIN_VALUE)); - - assertEquals(1, vmGcStats.size()); - VmGcStat stat = vmGcStats.get(0); - assertEquals(TIMESTAMP, (Long) stat.getTimeStamp()); - assertEquals(VM_ID, (Integer) stat.getVmId()); - assertEquals(COLLECTOR, stat.getCollectorName()); - assertEquals(RUN_COUNT, (Long) stat.getRunCount()); - assertEquals(WALL_TIME, (Long) stat.getWallTime()); - } - - @Test - public void testPutVmGcStat() { - Storage storage = mock(Storage.class); - VmGcStat stat = new VmGcStat(VM_ID, TIMESTAMP, COLLECTOR, RUN_COUNT, WALL_TIME); - VmGcStatDAO dao = new VmGcStatDAOImpl(storage); - dao.putVmGcStat(stat); - - verify(storage).putPojo(VmGcStatDAO.vmGcStatCategory, false, stat); - } -} diff -r 0ba74f790a8a -r ceb28ef8f9e8 distribution/config/commands/agent.properties --- a/distribution/config/commands/agent.properties Mon Jan 07 15:50:03 2013 -0500 +++ b/distribution/config/commands/agent.properties Mon Jan 07 15:50:59 2013 -0500 @@ -17,6 +17,8 @@ thermostat-vm-cpu-agent-@project.version@.jar, \ thermostat-vm-memory-common-@project.version@.jar, \ thermostat-vm-memory-agent-@project.version@.jar, \ + thermostat-vm-gc-common-@project.version@.jar, \ + thermostat-vm-gc-agent-@project.version@.jar, \ thermostat-vm-heap-analysis-common-@project.version@.jar, \ thermostat-vm-heap-analysis-agent-@project.version@.jar, \ thermostat-killvm-agent-@project.version@.jar, \ diff -r 0ba74f790a8a -r ceb28ef8f9e8 distribution/config/commands/gui.properties --- a/distribution/config/commands/gui.properties Mon Jan 07 15:50:03 2013 -0500 +++ b/distribution/config/commands/gui.properties Mon Jan 07 15:50:59 2013 -0500 @@ -25,6 +25,7 @@ thermostat-vm-cpu-common-@project.version@.jar, \ thermostat-vm-cpu-client-core-@project.version@.jar, \ thermostat-vm-cpu-client-swing-@project.version@.jar, \ + thermostat-vm-gc-common-@project.version@.jar, \ thermostat-vm-gc-client-core-@project.version@.jar, \ thermostat-vm-gc-client-swing-@project.version@.jar, \ thermostat-vm-memory-common-@project.version@.jar, \ diff -r 0ba74f790a8a -r ceb28ef8f9e8 distribution/pom.xml --- a/distribution/pom.xml Mon Jan 07 15:50:03 2013 -0500 +++ b/distribution/pom.xml Mon Jan 07 15:50:59 2013 -0500 @@ -427,6 +427,11 @@ com.redhat.thermostat + thermostat-vm-gc-agent + ${project.version} + + + com.redhat.thermostat thermostat-vm-classstat-client-swing ${project.version} diff -r 0ba74f790a8a -r ceb28ef8f9e8 eclipse/com.redhat.thermostat.client.feature/feature.xml --- a/eclipse/com.redhat.thermostat.client.feature/feature.xml Mon Jan 07 15:50:03 2013 -0500 +++ b/eclipse/com.redhat.thermostat.client.feature/feature.xml Mon Jan 07 15:50:59 2013 -0500 @@ -210,4 +210,11 @@ version="0.0.0" unpack="false"/> + + diff -r 0ba74f790a8a -r ceb28ef8f9e8 system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java --- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java Mon Jan 07 15:50:03 2013 -0500 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java Mon Jan 07 15:50:59 2013 -0500 @@ -98,22 +98,6 @@ return MonitoredVmUtil.jvmArgs(vm); } - public long getTotalCollectors() throws MonitorException { - return (Long) vm.findByName("sun.gc.policy.collectors").getValue(); - } - - public String getCollectorName(long collector) throws MonitorException { - return (String) vm.findByName("sun.gc.collector." + collector + ".name").getValue(); - } - - public long getCollectorTime(long collector) throws MonitorException { - return (Long) vm.findByName("sun.gc.collector." + collector + ".time").getValue(); - } - - public long getCollectorInvocations(long collector) throws MonitorException { - return (Long) vm.findByName("sun.gc.collector." + collector + ".invocations").getValue(); - } - public long getLoadedClasses() throws MonitorException { return (Long) vm.findByName("java.cls.loadedClasses").getValue(); } diff -r 0ba74f790a8a -r ceb28ef8f9e8 system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java --- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java Mon Jan 07 15:50:03 2013 -0500 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java Mon Jan 07 15:50:59 2013 -0500 @@ -59,7 +59,6 @@ import com.redhat.thermostat.agent.JvmStatusListener; import com.redhat.thermostat.agent.JvmStatusNotifier; import com.redhat.thermostat.common.dao.VmClassStatDAO; -import com.redhat.thermostat.common.dao.VmGcStatDAO; import com.redhat.thermostat.common.dao.VmInfoDAO; import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.storage.model.VmInfo; @@ -73,16 +72,14 @@ private final VmInfoDAO vmInfoDAO; private final VmClassStatDAO vmClassStatDAO; - private final VmGcStatDAO vmGcStatDAO; private Map monitoredVms = new HashMap<>(); private Map> registeredListeners = new ConcurrentHashMap<>(); private Set statusListeners = new CopyOnWriteArraySet(); - JvmStatHostListener(VmInfoDAO vmInfoDAO, VmGcStatDAO vmGcStatDAO, VmClassStatDAO vmClassStatDAO, boolean attachNew) { + JvmStatHostListener(VmInfoDAO vmInfoDAO, VmClassStatDAO vmClassStatDAO, boolean attachNew) { this.vmInfoDAO = vmInfoDAO; - this.vmGcStatDAO = vmGcStatDAO; this.vmClassStatDAO = vmClassStatDAO; this.attachNew = attachNew; } @@ -165,11 +162,7 @@ listeners = new CopyOnWriteArrayList<>(); } - VmListener listener = new JvmStatVmListener(vmGcStatDAO, vmId); - vm.addVmListener(listener); - listeners.add(listener); - - listener = new JvmStatVmClassListener(vmClassStatDAO, vmId); + VmListener listener = new JvmStatVmClassListener(vmClassStatDAO, vmId); vm.addVmListener(listener); listeners.add(listener); diff -r 0ba74f790a8a -r ceb28ef8f9e8 system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java --- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java Mon Jan 07 15:50:03 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.backend.system; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import sun.jvmstat.monitor.MonitorException; -import sun.jvmstat.monitor.MonitoredVm; -import sun.jvmstat.monitor.event.MonitorStatusChangeEvent; -import sun.jvmstat.monitor.event.VmEvent; -import sun.jvmstat.monitor.event.VmListener; - -import com.redhat.thermostat.common.dao.VmGcStatDAO; -import com.redhat.thermostat.common.utils.LoggingUtils; -import com.redhat.thermostat.storage.model.VmGcStat; - -public class JvmStatVmListener implements VmListener { - - private static final Logger logger = LoggingUtils.getLogger(JvmStatVmListener.class); - - private final int vmId; - private final VmGcStatDAO gcDAO; - - public JvmStatVmListener(VmGcStatDAO vmGcStatDao, int vmId) { - gcDAO = vmGcStatDao; - this.vmId = vmId; - } - - @Override - public void disconnected(VmEvent event) { - /* nothing to do here */ - } - - @Override - public void monitorStatusChanged(MonitorStatusChangeEvent event) { - /* nothing to do here */ - } - - @Override - public void monitorsUpdated(VmEvent event) { - MonitoredVm vm = event.getMonitoredVm(); - if (vm == null) { - throw new NullPointerException(); - } - recordGcStat(vm); - } - - private void recordGcStat(MonitoredVm vm) { - try { - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - long collectors = extractor.getTotalCollectors(); - for (int i = 0; i < collectors; i++) { - long timestamp = System.currentTimeMillis(); - VmGcStat stat = new VmGcStat(vmId, timestamp, - extractor.getCollectorName(i), - extractor.getCollectorInvocations(i), - extractor.getCollectorTime(i)); - gcDAO.putVmGcStat(stat); - } - } catch (MonitorException e) { - logger.log(Level.WARNING, "error gathering gc info for vm " + vmId, e); - } - - } - -} diff -r 0ba74f790a8a -r ceb28ef8f9e8 system-backend/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java --- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java Mon Jan 07 15:50:03 2013 -0500 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java Mon Jan 07 15:50:59 2013 -0500 @@ -93,7 +93,7 @@ protected void setDAOFactoryAction() { hostInfos = df.getHostInfoDAO(); networkInterfaces = df.getNetworkInterfaceInfoDAO(); - hostListener = new JvmStatHostListener(df.getVmInfoDAO(), df.getVmGcStatDAO(), df.getVmClassStatsDAO(), getObserveNewJvm()); + hostListener = new JvmStatHostListener(df.getVmInfoDAO(), df.getVmClassStatsDAO(), getObserveNewJvm()); } @Override diff -r 0ba74f790a8a -r ceb28ef8f9e8 system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatDataExtractorTest.java --- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatDataExtractorTest.java Mon Jan 07 15:50:03 2013 -0500 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatDataExtractorTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -174,58 +174,6 @@ } @Test - public void testTotalCollectors() throws MonitorException { - final String MONITOR_NAME = "sun.gc.policy.collectors"; - final Long MONITOR_VALUE = 9l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, MONITOR_VALUE); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getTotalCollectors(); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(MONITOR_VALUE, returned); - } - - @Test - public void testCollectorName() throws MonitorException { - final String MONITOR_NAME = "sun.gc.collector.0.name"; - final String COLLECTOR_NAME = "SomeMemoryCollector"; - MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, COLLECTOR_NAME); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - String returned = extractor.getCollectorName(0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(COLLECTOR_NAME, returned); - } - - @Test - public void testCollectorTime() throws MonitorException { - final String MONITOR_NAME = "sun.gc.collector.0.time"; - final Long COLLECTOR_TIME = 99l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_TIME); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getCollectorTime(0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(COLLECTOR_TIME, returned); - } - - @Test - public void testCollectorInvocations() throws MonitorException { - final String MONITOR_NAME = "sun.gc.collector.0.invocations"; - final Long COLLECTOR_INVOCATIONS = 99l; - MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_INVOCATIONS); - - JvmStatDataExtractor extractor = new JvmStatDataExtractor(vm); - Long returned = extractor.getCollectorInvocations(0); - - verify(vm).findByName(eq(MONITOR_NAME)); - assertEquals(COLLECTOR_INVOCATIONS, returned); - } - - @Test public void testLoadedClasses() throws MonitorException { final String MONITOR_NAME = "java.cls.loadedClasses"; final Long LOADED_CLASSES = 99l; diff -r 0ba74f790a8a -r ceb28ef8f9e8 system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java --- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java Mon Jan 07 15:50:03 2013 -0500 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/JvmStatHostListenerTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -81,7 +81,7 @@ VmClassStatDAO vmClassDAO = mock(VmClassStatDAO.class); VmInfoDAO vmInfoDAO = mock(VmInfoDAO.class); - JvmStatHostListener l = new JvmStatHostListener(vmInfoDAO, null, vmClassDAO ,true); + JvmStatHostListener l = new JvmStatHostListener(vmInfoDAO, vmClassDAO ,true); SystemBackend backend = mock(SystemBackend.class); when(backend.getObserveNewJvm()).thenReturn(true); diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/agent/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/agent/pom.xml Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,78 @@ + + + 4.0.0 + + thermostat-vm-gc + com.redhat.thermostat + 0.5.0-SNAPSHOT + + thermostat-vm-gc-agent + bundle + Thermostat VM GC Agent plugin + + + + org.apache.felix + maven-bundle-plugin + true + + + Red Hat, Inc. + com.redhat.thermostat.vm.gc.agent + com.redhat.thermostat.vm.gc.agent.internal.Activator + + com.redhat.thermostat.vm.gc.agent + + + com.redhat.thermostat.vm.gc.agent.internal + + + <_nouses>true + + + + + + + + junit + junit + test + + + org.mockito + mockito-core + test + + + org.osgi + org.osgi.core + provided + + + org.osgi + org.osgi.compendium + provided + + + com.redhat.thermostat + thermostat-common-core + ${project.version} + + + com.redhat.thermostat + thermostat-vm-gc-common + ${project.version} + + + com.redhat.thermostat + thermostat-agent-core + ${project.version} + + + com.redhat.thermostat + thermostat-storage-core + ${project.version} + + + diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/Activator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/Activator.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,97 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.agent.internal; + +import java.util.Map; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; + +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.backend.BackendService; +import com.redhat.thermostat.common.MultipleServiceTracker; +import com.redhat.thermostat.common.MultipleServiceTracker.Action; +import com.redhat.thermostat.common.Version; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; + +public class Activator implements BundleActivator { + + private MultipleServiceTracker tracker; + private VmGcBackend backend; + private ServiceRegistration reg; + + @Override + public void start(final BundleContext context) throws Exception { + Class[] deps = new Class[] { + BackendService.class, + VmGcStatDAO.class + }; + tracker = new MultipleServiceTracker(context, deps, new Action() { + + @Override + public void dependenciesAvailable(Map services) { + VmGcStatDAO vmGcStatDao = (VmGcStatDAO) services.get(VmGcStatDAO.class.getName()); + Version version = new Version(context.getBundle()); + backend = new VmGcBackend(vmGcStatDao, version); + reg = context.registerService(Backend.class.getName(), backend, null); + } + + @Override + public void dependenciesUnavailable() { + if (backend.isActive()) { + backend.deactivate(); + } + reg.unregister(); + } + + }); + tracker.open(); + } + + @Override + public void stop(BundleContext context) throws Exception { + tracker.close(); + } + + /* + * For testing purposes only. + */ + VmGcBackend getBackend() { + return backend; + } +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcBackend.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcBackend.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,141 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.agent.internal; + +import java.net.URISyntaxException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import sun.jvmstat.monitor.HostIdentifier; +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredHost; + +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.backend.BackendID; +import com.redhat.thermostat.backend.BackendsProperties; +import com.redhat.thermostat.common.Version; +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; + +public class VmGcBackend extends Backend { + + private static final Logger LOGGER = LoggingUtils.getLogger(VmGcBackend.class); + + private VmGcStatDAO vmGcStats; + private HostIdentifier hostId; + private MonitoredHost host; + private VmGcHostListener hostListener; + private boolean started; + + public VmGcBackend(VmGcStatDAO vmGcStatDAO, Version version) { + super(new BackendID("VM GC Backend", VmGcBackend.class.getName())); + this.vmGcStats = vmGcStatDAO; + + setConfigurationValue(BackendsProperties.VENDOR.name(), "Red Hat, Inc."); + setConfigurationValue(BackendsProperties.DESCRIPTION.name(), "Gathers garbage collection statistics about a JVM"); + setConfigurationValue(BackendsProperties.VERSION.name(), version.getVersionNumber()); + + try { + hostId = new HostIdentifier((String) null); + host = MonitoredHost.getMonitoredHost(hostId); + hostListener = new VmGcHostListener(vmGcStats, attachToNewProcessByDefault()); + } catch (MonitorException me) { + LOGGER.log(Level.WARNING, "Problems with connecting jvmstat to local machine", me); + } catch (URISyntaxException use) { + LOGGER.log(Level.WARNING, "Failed to create host identifier", use); + } + } + + @Override + public boolean activate() { + if (!started && host != null) { + try { + host.addHostListener(hostListener); + started = true; + } catch (MonitorException me) { + LOGGER.log(Level.WARNING, "problems with connecting jvmstat to local machine", me); + } + } + return started; + } + + @Override + public boolean deactivate() { + if (started && host != null) { + try { + host.removeHostListener(hostListener); + started = false; + } catch (MonitorException me) { + LOGGER.log(Level.INFO, "something went wrong in jvmstat's listening to this host"); + } + } + return !started; + } + + @Override + public boolean isActive() { + return started; + } + + @Override + protected void setDAOFactoryAction() { + // No need for DAOFactory + } + + @Override + public String getConfigurationValue(String key) { + return null; + } + + @Override + public boolean attachToNewProcessByDefault() { + return true; + } + + @Override + public int getOrderValue() { + return ORDER_MEMORY_GROUP + 20; + } + + /* + * For testing purposes only. + */ + void setHost(MonitoredHost host) { + this.host = host; + } + +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcDataExtractor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcDataExtractor.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,84 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.agent.internal; + +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredVm; + +/** + * A helper class to provide type-safe access to commonly used jvmstat monitors + *

+ * Implementation details: For local vms, jvmstat uses a ByteBuffer + * corresponding to mmap()ed hsperfdata file. The hsperfdata file is updated + * asynchronously by the vm that created the file. The polling that jvmstat api + * provides is merely an abstraction over this (possibly always up-to-date) + * ByteBuffer. So the data this class extracts is as current as possible, and + * does not correspond to when the jvmstat update events fired. + */ +public class VmGcDataExtractor { + + /* + * Note, there may be a performance issue to consider here. We have a lot of + * string constants. When we start adding some of the more heavyweight + * features, and running into CPU issues this may need to be reconsidered in + * order to avoid the String pool overhead. See also: + * http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#intern() + */ + + private final MonitoredVm vm; + + public VmGcDataExtractor(MonitoredVm vm) { + this.vm = vm; + } + + public long getTotalCollectors() throws MonitorException { + return (Long) vm.findByName("sun.gc.policy.collectors").getValue(); + } + + public String getCollectorName(long collector) throws MonitorException { + return (String) vm.findByName("sun.gc.collector." + collector + ".name").getValue(); + } + + public long getCollectorTime(long collector) throws MonitorException { + return (Long) vm.findByName("sun.gc.collector." + collector + ".time").getValue(); + } + + public long getCollectorInvocations(long collector) throws MonitorException { + return (Long) vm.findByName("sun.gc.collector." + collector + ".invocations").getValue(); + } + +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcHostListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcHostListener.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,171 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.agent.internal; + +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredHost; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.VmIdentifier; +import sun.jvmstat.monitor.event.HostEvent; +import sun.jvmstat.monitor.event.HostListener; +import sun.jvmstat.monitor.event.VmListener; +import sun.jvmstat.monitor.event.VmStatusChangeEvent; + +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; + +public class VmGcHostListener implements HostListener { + + private static final Logger logger = LoggingUtils.getLogger(VmGcHostListener.class); + + private boolean attachNew; + + private final VmGcStatDAO vmGcStatDAO; + + private Map monitoredVms = new HashMap<>(); + private Map registeredListeners = new ConcurrentHashMap<>(); + + VmGcHostListener(VmGcStatDAO vmGcStatDAO, boolean attachNew) { + this.vmGcStatDAO = vmGcStatDAO; + this.attachNew = attachNew; + } + + void removeAllListeners() { + for (MonitoredVm vm : monitoredVms.values()) { + VmListener listener = registeredListeners.get(vm); + try { + if (listener != null) { + vm.removeVmListener(listener); + } + } catch (MonitorException e) { + logger.log(Level.WARNING, "can't remove vm listener", e); + } + } + } + + @Override + public void disconnected(HostEvent event) { + logger.warning("Disconnected from host"); + } + + @SuppressWarnings("unchecked") // Unchecked casts to (Set). + @Override + public void vmStatusChanged(VmStatusChangeEvent event) { + MonitoredHost host = event.getMonitoredHost(); + + for (Integer newVm : (Set) event.getStarted()) { + try { + logger.fine("New vm: " + newVm); + sendNewVM(newVm, host); + } catch (MonitorException e) { + logger.log(Level.WARNING, "error getting info for new vm" + newVm, e); + } catch (URISyntaxException e) { + logger.log(Level.WARNING, "error getting info for new vm" + newVm, e); + } + } + + for (Integer stoppedVm : (Set) event.getTerminated()) { + try { + logger.fine("stopped vm: " + stoppedVm); + sendStoppedVM(stoppedVm, host); + } catch (URISyntaxException e) { + logger.log(Level.WARNING, "error getting info for stopped vm" + stoppedVm, e); + } catch (MonitorException e) { + logger.log(Level.WARNING, "error getting info for stopped vm" + stoppedVm, e); + } + } + } + + private void sendNewVM(Integer vmId, MonitoredHost host) + throws MonitorException, URISyntaxException { + MonitoredVm vm = host.getMonitoredVm(host.getHostIdentifier().resolve( + new VmIdentifier(vmId.toString()))); + if (vm != null) { + if (attachNew) { + VmGcVmListener listener = new VmGcVmListener(vmGcStatDAO, vmId); + vm.addVmListener(listener); + + registeredListeners.put(vm, listener); + logger.finer("Attached VmListener for VM: " + vmId); + } else { + logger.log(Level.FINE, "skipping new vm " + vmId); + } + + monitoredVms.put(vmId, vm); + } + } + + private void sendStoppedVM(Integer vmId, MonitoredHost host) throws URISyntaxException, MonitorException { + + VmIdentifier resolvedVmID = host.getHostIdentifier().resolve(new VmIdentifier(vmId.toString())); + if (resolvedVmID != null) { + MonitoredVm vm = monitoredVms.remove(vmId); + VmListener listener = registeredListeners.remove(vm); + try { + if (listener != null) { + vm.removeVmListener(listener); + } + } catch (MonitorException e) { + logger.log(Level.WARNING, "can't remove vm listener", e); + } + vm.detach(); + } + } + + /* + * For testing purposes only. + */ + Map getMonitoredVms() { + return monitoredVms; + } + + /* + * For testing purposes only. + */ + Map getRegisteredListeners() { + return registeredListeners; + } + +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcVmListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/agent/src/main/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcVmListener.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,102 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.agent.internal; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.event.MonitorStatusChangeEvent; +import sun.jvmstat.monitor.event.VmEvent; +import sun.jvmstat.monitor.event.VmListener; + +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.storage.model.VmGcStat; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; + +public class VmGcVmListener implements VmListener { + + private static final Logger logger = LoggingUtils.getLogger(VmGcVmListener.class); + + private final int vmId; + private final VmGcStatDAO gcDAO; + + public VmGcVmListener(VmGcStatDAO vmGcStatDao, int vmId) { + gcDAO = vmGcStatDao; + this.vmId = vmId; + } + + @Override + public void disconnected(VmEvent event) { + /* nothing to do here */ + } + + @Override + public void monitorStatusChanged(MonitorStatusChangeEvent event) { + /* nothing to do here */ + } + + @Override + public void monitorsUpdated(VmEvent event) { + MonitoredVm vm = event.getMonitoredVm(); + if (vm == null) { + throw new NullPointerException(); + } + + VmGcDataExtractor extractor = new VmGcDataExtractor(vm); + recordGcStat(vm, extractor); + } + + void recordGcStat(MonitoredVm vm, VmGcDataExtractor extractor) { + try { + long collectors = extractor.getTotalCollectors(); + for (int i = 0; i < collectors; i++) { + long timestamp = System.currentTimeMillis(); + VmGcStat stat = new VmGcStat(vmId, timestamp, + extractor.getCollectorName(i), + extractor.getCollectorInvocations(i), + extractor.getCollectorTime(i)); + gcDAO.putVmGcStat(stat); + } + } catch (MonitorException e) { + logger.log(Level.WARNING, "error gathering gc info for vm " + vmId, e); + } + + } + +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/ActivatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/ActivatorTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,104 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.agent.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.Test; +import org.osgi.framework.Bundle; +import org.osgi.framework.Version; + +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.backend.BackendService; +import com.redhat.thermostat.test.StubBundleContext; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; + +public class ActivatorTest { + + @Test + public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception { + StubBundleContext context = new StubBundleContext(); + + Activator activator = new Activator(); + + activator.start(context); + + assertEquals(0, context.getAllServices().size()); + assertEquals(2, context.getServiceListeners().size()); + + activator.stop(context); + } + + @Test + public void verifyActivatorRegistersServices() throws Exception { + StubBundleContext context = new StubBundleContext() { + @Override + public Bundle getBundle() { + Bundle result = mock(Bundle.class); + when(result.getVersion()).thenReturn(Version.emptyVersion); + return result; + } + }; + + BackendService service = mock(BackendService.class); + VmGcStatDAO vmGcStatDAO = mock(VmGcStatDAO.class); + + context.registerService(BackendService.class, service, null); + context.registerService(VmGcStatDAO.class, vmGcStatDAO, null); + + Activator activator = new Activator(); + + activator.start(context); + + assertTrue(context.isServiceRegistered(Backend.class.getName(), VmGcBackend.class)); + VmGcBackend backend = activator.getBackend(); + assertNotNull(backend); + + activator.stop(context); + + assertFalse(backend.isActive()); + + assertEquals(0, context.getServiceListeners().size()); + assertEquals(2, context.getAllServices().size()); + } + +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcBackendTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcBackendTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,91 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.agent.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.net.URISyntaxException; + +import org.junit.Before; +import org.junit.Test; + +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredHost; +import sun.jvmstat.monitor.event.HostListener; + +import com.redhat.thermostat.common.Version; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; + +public class VmGcBackendTest { + + private VmGcBackend backend; + private MonitoredHost host; + + @Before + public void setup() throws MonitorException, URISyntaxException { + VmGcStatDAO vmGcStatDao = mock(VmGcStatDAO.class); + + Version version = mock(Version.class); + when(version.getVersionNumber()).thenReturn("0.0.0"); + + backend = new VmGcBackend(vmGcStatDao, version); + + host = mock(MonitoredHost.class); + backend.setHost(host); + } + + @Test + public void testStart() throws MonitorException { + backend.activate(); + verify(host).addHostListener(any(HostListener.class)); + assertTrue(backend.isActive()); + } + + @Test + public void testStop() throws MonitorException { + backend.activate(); + backend.deactivate(); + verify(host).removeHostListener(any(HostListener.class)); + assertFalse(backend.isActive()); + } + +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcDataExtractorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcDataExtractorTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,124 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.agent.internal; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Test; + +import sun.jvmstat.monitor.LongMonitor; +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.StringMonitor; + +public class VmGcDataExtractorTest { + + private MonitoredVm buildStringMonitoredVm(String monitorName, String monitorReturn) throws MonitorException { + final StringMonitor monitor = mock(StringMonitor.class); + when(monitor.stringValue()).thenReturn(monitorReturn); + when(monitor.getValue()).thenReturn(monitorReturn); + MonitoredVm vm = mock(MonitoredVm.class); + when(vm.findByName(monitorName)).thenReturn(monitor); + return vm; + } + + private MonitoredVm buildLongMonitoredVm(String monitorName, Long monitorReturn) throws MonitorException { + final LongMonitor monitor = mock(LongMonitor.class); + when(monitor.longValue()).thenReturn(monitorReturn); + when(monitor.getValue()).thenReturn(monitorReturn); + MonitoredVm vm = mock(MonitoredVm.class); + when(vm.findByName(monitorName)).thenReturn(monitor); + return vm; + } + + @Test + public void testTotalCollectors() throws MonitorException { + final String MONITOR_NAME = "sun.gc.policy.collectors"; + final Long MONITOR_VALUE = 9l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, MONITOR_VALUE); + + VmGcDataExtractor extractor = new VmGcDataExtractor(vm); + Long returned = extractor.getTotalCollectors(); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(MONITOR_VALUE, returned); + } + + @Test + public void testCollectorName() throws MonitorException { + final String MONITOR_NAME = "sun.gc.collector.0.name"; + final String COLLECTOR_NAME = "SomeMemoryCollector"; + MonitoredVm vm = buildStringMonitoredVm(MONITOR_NAME, COLLECTOR_NAME); + + VmGcDataExtractor extractor = new VmGcDataExtractor(vm); + String returned = extractor.getCollectorName(0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(COLLECTOR_NAME, returned); + } + + @Test + public void testCollectorTime() throws MonitorException { + final String MONITOR_NAME = "sun.gc.collector.0.time"; + final Long COLLECTOR_TIME = 99l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_TIME); + + VmGcDataExtractor extractor = new VmGcDataExtractor(vm); + Long returned = extractor.getCollectorTime(0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(COLLECTOR_TIME, returned); + } + + @Test + public void testCollectorInvocations() throws MonitorException { + final String MONITOR_NAME = "sun.gc.collector.0.invocations"; + final Long COLLECTOR_INVOCATIONS = 99l; + MonitoredVm vm = buildLongMonitoredVm(MONITOR_NAME, COLLECTOR_INVOCATIONS); + + VmGcDataExtractor extractor = new VmGcDataExtractor(vm); + Long returned = extractor.getCollectorInvocations(0); + + verify(vm).findByName(eq(MONITOR_NAME)); + assertEquals(COLLECTOR_INVOCATIONS, returned); + } + +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcHostListenerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcHostListenerTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,136 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.agent.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Before; +import org.junit.Test; + +import sun.jvmstat.monitor.HostIdentifier; +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredHost; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.VmIdentifier; +import sun.jvmstat.monitor.event.VmStatusChangeEvent; + +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; + +public class VmGcHostListenerTest { + + private VmGcHostListener hostListener; + private MonitoredHost host; + private MonitoredVm monitoredVm1; + private MonitoredVm monitoredVm2; + + @Before + public void setup() throws MonitorException, URISyntaxException { + VmGcStatDAO vmGcStatDAO = mock(VmGcStatDAO.class); + hostListener = new VmGcHostListener(vmGcStatDAO, true); + + host = mock(MonitoredHost.class); + HostIdentifier hostId = mock(HostIdentifier.class); + monitoredVm1 = mock(MonitoredVm.class); + monitoredVm2 = mock(MonitoredVm.class); + VmIdentifier vmId1 = new VmIdentifier("1"); + VmIdentifier vmId2 = new VmIdentifier("2"); + when(host.getHostIdentifier()).thenReturn(hostId); + when(host.getMonitoredVm(eq(vmId1))).thenReturn(monitoredVm1); + when(host.getMonitoredVm(eq(vmId2))).thenReturn(monitoredVm2); + when(hostId.resolve(eq(vmId1))).thenReturn(vmId1); + when(hostId.resolve(eq(vmId2))).thenReturn(vmId2); + } + + @Test + public void testNewVM() throws InterruptedException, MonitorException { + startVMs(); + + assertTrue(hostListener.getMonitoredVms().containsKey(1)); + assertTrue(hostListener.getMonitoredVms().containsKey(2)); + assertEquals(monitoredVm1, hostListener.getMonitoredVms().get(1)); + assertEquals(monitoredVm2, hostListener.getMonitoredVms().get(2)); + + assertTrue(hostListener.getRegisteredListeners().containsKey(monitoredVm1)); + assertTrue(hostListener.getRegisteredListeners().containsKey(monitoredVm2)); + } + + @Test + public void testStoppedVM() throws InterruptedException, MonitorException { + final Set stopped = new HashSet<>(); + stopped.add(1); + + startVMs(); + + // Trigger a change event + VmStatusChangeEvent event = mock(VmStatusChangeEvent.class); + when(event.getMonitoredHost()).thenReturn(host); + when(event.getStarted()).thenReturn(Collections.emptySet()); + when(event.getTerminated()).thenReturn(stopped); + hostListener.vmStatusChanged(event); + + // Ensure only 1 removed + assertFalse(hostListener.getMonitoredVms().containsKey(1)); + assertTrue(hostListener.getMonitoredVms().containsKey(2)); + assertEquals(monitoredVm2, hostListener.getMonitoredVms().get(2)); + + assertFalse(hostListener.getRegisteredListeners().containsKey(monitoredVm1)); + assertTrue(hostListener.getRegisteredListeners().containsKey(monitoredVm2)); + } + + private void startVMs() throws InterruptedException, MonitorException { + final Set started = new HashSet<>(); + started.add(1); + started.add(2); + + // Trigger a change event + VmStatusChangeEvent event = mock(VmStatusChangeEvent.class); + when(event.getMonitoredHost()).thenReturn(host); + when(event.getStarted()).thenReturn(started); + when(event.getTerminated()).thenReturn(Collections.emptySet()); + hostListener.vmStatusChanged(event); + } +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcVmListenerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/agent/src/test/java/com/redhat/thermostat/vm/gc/agent/internal/VmGcVmListenerTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,112 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.agent.internal; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredVm; + +import com.redhat.thermostat.storage.model.VmGcStat; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; + +public class VmGcVmListenerTest { + private static final String[] GC_NAMES = new String[] { "GC1", "GC2" }; + private static final Long[] GC_INVOCS = new Long[] { 500L, 1000L }; + private static final Long[] GC_TIMES = new Long[] { 5000L, 10000L }; + + private VmGcVmListener vmListener; + private MonitoredVm monitoredVm; + private VmGcDataExtractor extractor; + private VmGcStatDAO vmGcStatDAO; + + @Before + public void setup() throws MonitorException { + final int numGCs = 2; + vmGcStatDAO = mock(VmGcStatDAO.class); + vmListener = new VmGcVmListener(vmGcStatDAO, 0); + + monitoredVm = mock(MonitoredVm.class); + extractor = mock(VmGcDataExtractor.class); + + for (int i = 0; i < numGCs; i++) { + mockCollectorName(i); + mockCollectorInvocations(i); + mockCollectorTime(i); + } + + when(extractor.getTotalCollectors()).thenReturn((long) GC_NAMES.length); + } + + private void mockCollectorName(int gc) throws MonitorException { + when(extractor.getCollectorName(gc)).thenReturn(GC_NAMES[gc]); + } + + private void mockCollectorInvocations(int gc) throws MonitorException { + when(extractor.getCollectorInvocations(gc)).thenReturn(GC_INVOCS[gc]); + } + + private void mockCollectorTime(int gc) throws MonitorException { + when(extractor.getCollectorTime(gc)).thenReturn(GC_TIMES[gc]); + } + + @Test + public void testRecordMemoryStat() { + final int numCollectors = GC_NAMES.length; + vmListener.recordGcStat(monitoredVm, extractor); + ArgumentCaptor captor = ArgumentCaptor.forClass(VmGcStat.class); + verify(vmGcStatDAO, times(numCollectors)).putVmGcStat(captor.capture()); + List gcStats = captor.getAllValues(); + + for (int i = 0; i < numCollectors; i++) { + VmGcStat stat = gcStats.get(i); + assertEquals(GC_NAMES[i], stat.getCollectorName()); + assertEquals(GC_INVOCS[i], (Long) stat.getRunCount()); + assertEquals(GC_TIMES[i], (Long) stat.getWallTime()); + } + } +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/client-core/pom.xml --- a/vm-gc/client-core/pom.xml Mon Jan 07 15:50:03 2013 -0500 +++ b/vm-gc/client-core/pom.xml Mon Jan 07 15:50:59 2013 -0500 @@ -67,6 +67,11 @@ com.redhat.thermostat + thermostat-vm-gc-common + ${project.version} + + + com.redhat.thermostat thermostat-client-core ${project.version} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/VmGcService.java --- a/vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/VmGcService.java Mon Jan 07 15:50:03 2013 -0500 +++ b/vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/VmGcService.java Mon Jan 07 15:50:59 2013 -0500 @@ -41,10 +41,10 @@ import com.redhat.thermostat.client.core.NameMatchingRefFilter; import com.redhat.thermostat.client.core.controllers.InformationServiceController; import com.redhat.thermostat.common.ApplicationService; -import com.redhat.thermostat.common.dao.VmGcStatDAO; import com.redhat.thermostat.common.dao.VmRef; import com.redhat.thermostat.common.utils.OSGIUtils; import com.redhat.thermostat.vm.gc.client.core.internal.VmGcController; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; import com.redhat.thermostat.vm.memory.common.VmMemoryStatDAO; public class VmGcService implements InformationService { diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/internal/Activator.java --- a/vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/internal/Activator.java Mon Jan 07 15:50:03 2013 -0500 +++ b/vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/internal/Activator.java Mon Jan 07 15:50:59 2013 -0500 @@ -50,9 +50,9 @@ import com.redhat.thermostat.common.Constants; import com.redhat.thermostat.common.MultipleServiceTracker; import com.redhat.thermostat.common.MultipleServiceTracker.Action; -import com.redhat.thermostat.common.dao.VmGcStatDAO; import com.redhat.thermostat.common.dao.VmRef; import com.redhat.thermostat.vm.gc.client.core.VmGcService; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; import com.redhat.thermostat.vm.memory.common.VmMemoryStatDAO; public class Activator implements BundleActivator { diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/internal/VmGcController.java --- a/vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/internal/VmGcController.java Mon Jan 07 15:50:03 2013 -0500 +++ b/vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/internal/VmGcController.java Mon Jan 07 15:50:59 2013 -0500 @@ -55,7 +55,6 @@ import com.redhat.thermostat.common.NotImplementedException; import com.redhat.thermostat.common.Timer; import com.redhat.thermostat.common.Timer.SchedulingType; -import com.redhat.thermostat.common.dao.VmGcStatDAO; import com.redhat.thermostat.common.dao.VmRef; import com.redhat.thermostat.common.locale.Translate; import com.redhat.thermostat.storage.model.IntervalTimeData; @@ -66,6 +65,7 @@ import com.redhat.thermostat.vm.gc.client.core.VmGcView; import com.redhat.thermostat.vm.gc.client.core.VmGcViewProvider; import com.redhat.thermostat.vm.gc.client.locale.LocaleResources; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; import com.redhat.thermostat.vm.memory.common.VmMemoryStatDAO; public class VmGcController implements InformationServiceController { diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/internal/ActivatorTest.java --- a/vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/internal/ActivatorTest.java Mon Jan 07 15:50:03 2013 -0500 +++ b/vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/internal/ActivatorTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -45,9 +45,9 @@ import com.redhat.thermostat.client.core.InformationService; import com.redhat.thermostat.common.ApplicationService; -import com.redhat.thermostat.common.dao.VmGcStatDAO; import com.redhat.thermostat.test.StubBundleContext; import com.redhat.thermostat.vm.gc.client.core.VmGcService; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; import com.redhat.thermostat.vm.memory.common.VmMemoryStatDAO; public class ActivatorTest { diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/internal/VmGcControllerTest.java --- a/vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/internal/VmGcControllerTest.java Mon Jan 07 15:50:03 2013 -0500 +++ b/vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/internal/VmGcControllerTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -58,13 +58,13 @@ import com.redhat.thermostat.common.Timer; import com.redhat.thermostat.common.Timer.SchedulingType; import com.redhat.thermostat.common.TimerFactory; -import com.redhat.thermostat.common.dao.VmGcStatDAO; import com.redhat.thermostat.common.dao.VmRef; import com.redhat.thermostat.storage.model.VmGcStat; import com.redhat.thermostat.storage.model.VmMemoryStat; import com.redhat.thermostat.storage.model.VmMemoryStat.Generation; import com.redhat.thermostat.vm.gc.client.core.VmGcView; import com.redhat.thermostat.vm.gc.client.core.VmGcViewProvider; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; import com.redhat.thermostat.vm.memory.common.VmMemoryStatDAO; public class VmGcControllerTest { diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/common/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/common/pom.xml Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,68 @@ + + + 4.0.0 + + thermostat-vm-gc + com.redhat.thermostat + 0.5.0-SNAPSHOT + + thermostat-vm-gc-common + bundle + Thermostat VM GC Common plugin + + + + org.apache.felix + maven-bundle-plugin + true + + + Red Hat, Inc. + com.redhat.thermostat.vm.gc.common + com.redhat.thermostat.vm.gc.common.internal.Activator + + com.redhat.thermostat.vm.gc.common + + + com.redhat.thermostat.vm.gc.common.internal + + + <_nouses>true + + + + + + + + junit + junit + test + + + org.mockito + mockito-core + test + + + org.osgi + org.osgi.core + provided + + + org.osgi + org.osgi.compendium + provided + + + com.redhat.thermostat + thermostat-common-core + ${project.version} + + + com.redhat.thermostat + thermostat-storage-core + ${project.version} + + + diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/VmGcStatDAO.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/VmGcStatDAO.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,60 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.common; + +import java.util.List; + +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.storage.core.Category; +import com.redhat.thermostat.storage.core.Key; +import com.redhat.thermostat.storage.model.VmGcStat; + +public interface VmGcStatDAO { + + static final Key collectorKey = new Key<>("collectorName", false); + static final Key runCountKey = new Key<>("runCount", false); + /** time in microseconds */ + static final Key wallTimeKey = new Key<>("wallTime", false); + + static final Category vmGcStatCategory = new Category("vm-gc-stats", + Key.AGENT_ID, Key.VM_ID, Key.TIMESTAMP, collectorKey, + runCountKey, wallTimeKey); + + public List getLatestVmGcStats(VmRef ref, long since); + + public void putVmGcStat(VmGcStat stat); +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/Activator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/Activator.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,79 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.common.internal; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.util.tracker.ServiceTracker; + +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; + +public class Activator implements BundleActivator { + + private ServiceTracker tracker; + private ServiceRegistration reg; + + @Override + public void start(BundleContext context) throws Exception { + tracker = new ServiceTracker(context, Storage.class.getName(), null) { + @Override + public Object addingService(ServiceReference reference) { + Storage storage = (Storage) context.getService(reference); + VmGcStatDAO vmGcStatDao = new VmGcStatDAOImpl(storage); + reg = context.registerService(VmGcStatDAO.class.getName(), vmGcStatDao, null); + return super.addingService(reference); + } + + @Override + public void removedService(ServiceReference reference, + Object service) { + reg.unregister(); + super.removedService(reference, service); + } + }; + tracker.open(); + } + + @Override + public void stop(BundleContext context) throws Exception { + tracker.close(); + } + +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatDAOImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatDAOImpl.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,68 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.common.internal; + +import java.util.List; + +import com.redhat.thermostat.common.dao.VmLatestPojoListGetter; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.storage.model.VmGcStat; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; + +public class VmGcStatDAOImpl implements VmGcStatDAO { + + private final Storage storage; + private final VmLatestPojoListGetter getter; + + VmGcStatDAOImpl(Storage storage) { + this.storage = storage; + storage.registerCategory(vmGcStatCategory); + getter = new VmLatestPojoListGetter<>(storage, vmGcStatCategory, VmGcStat.class); + } + + @Override + public List getLatestVmGcStats(VmRef ref, long since) { + return getter.getLatest(ref, since); + } + + @Override + public void putVmGcStat(VmGcStat stat) { + storage.putPojo(vmGcStatCategory, false, stat); + } + +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/ActivatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/ActivatorTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,84 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.common.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import org.junit.Test; + +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.test.StubBundleContext; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; + +public class ActivatorTest { + + @Test + public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception { + StubBundleContext context = new StubBundleContext(); + + Activator activator = new Activator(); + + activator.start(context); + + assertEquals(0, context.getAllServices().size()); + assertEquals(1, context.getServiceListeners().size()); + + activator.stop(context); + } + + @Test + public void verifyActivatorRegistersServices() throws Exception { + StubBundleContext context = new StubBundleContext(); + Storage storage = mock(Storage.class); + + context.registerService(Storage.class, storage, null); + + Activator activator = new Activator(); + + activator.start(context); + + assertTrue(context.isServiceRegistered(VmGcStatDAO.class.getName(), VmGcStatDAOImpl.class)); + + activator.stop(context); + + assertEquals(0, context.getServiceListeners().size()); + assertEquals(1, context.getAllServices().size()); + } + +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatDAOTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatDAOTest.java Mon Jan 07 15:50:59 2013 -0500 @@ -0,0 +1,133 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.vm.gc.common.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +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.util.Collection; +import java.util.List; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.common.dao.HostRef; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.storage.core.Cursor; +import com.redhat.thermostat.storage.core.Key; +import com.redhat.thermostat.storage.core.Query; +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.storage.core.Query.Criteria; +import com.redhat.thermostat.storage.model.VmGcStat; +import com.redhat.thermostat.test.MockQuery; +import com.redhat.thermostat.vm.gc.common.VmGcStatDAO; +import com.redhat.thermostat.vm.gc.common.internal.VmGcStatDAOImpl; + +public class VmGcStatDAOTest { + + private static final Integer VM_ID = 123; + private static final Long TIMESTAMP = 456L; + private static final String COLLECTOR = "collector1"; + private static final Long RUN_COUNT = 10L; + private static final Long WALL_TIME = 9L; + + @Test + public void testCategory() { + assertEquals("vm-gc-stats", VmGcStatDAO.vmGcStatCategory.getName()); + Collection> keys = VmGcStatDAO.vmGcStatCategory.getKeys(); + assertTrue(keys.contains(new Key<>("agentId", true))); + assertTrue(keys.contains(new Key("vmId", true))); + assertTrue(keys.contains(new Key("timeStamp", false))); + assertTrue(keys.contains(new Key("collectorName", false))); + assertTrue(keys.contains(new Key("runCount", false))); + assertTrue(keys.contains(new Key("wallTime", false))); + assertEquals(6, keys.size()); + } + + @Test + public void testGetLatestVmGcStatsBasic() { + + VmGcStat vmGcStat = new VmGcStat(VM_ID, TIMESTAMP, COLLECTOR, RUN_COUNT, WALL_TIME); + + @SuppressWarnings("unchecked") + Cursor cursor = mock(Cursor.class); + when(cursor.hasNext()).thenReturn(true).thenReturn(false); + when(cursor.next()).thenReturn(vmGcStat); + + Storage storage = mock(Storage.class); + when(storage.createQuery()).thenReturn(new MockQuery()); + when(storage.findAllPojos(any(Query.class), same(VmGcStat.class))).thenReturn(cursor); + + HostRef hostRef = mock(HostRef.class); + when(hostRef.getAgentId()).thenReturn("system"); + + VmRef vmRef = mock(VmRef.class); + when(vmRef.getAgent()).thenReturn(hostRef); + when(vmRef.getId()).thenReturn(321); + + + VmGcStatDAO dao = new VmGcStatDAOImpl(storage); + List vmGcStats = dao.getLatestVmGcStats(vmRef, Long.MIN_VALUE); + + ArgumentCaptor arg = ArgumentCaptor.forClass(MockQuery.class); + verify(storage).findAllPojos(arg.capture(), same(VmGcStat.class)); + assertTrue(arg.getValue().hasWhereClause(Key.TIMESTAMP, Criteria.GREATER_THAN, Long.MIN_VALUE)); + + assertEquals(1, vmGcStats.size()); + VmGcStat stat = vmGcStats.get(0); + assertEquals(TIMESTAMP, (Long) stat.getTimeStamp()); + assertEquals(VM_ID, (Integer) stat.getVmId()); + assertEquals(COLLECTOR, stat.getCollectorName()); + assertEquals(RUN_COUNT, (Long) stat.getRunCount()); + assertEquals(WALL_TIME, (Long) stat.getWallTime()); + } + + @Test + public void testPutVmGcStat() { + Storage storage = mock(Storage.class); + VmGcStat stat = new VmGcStat(VM_ID, TIMESTAMP, COLLECTOR, RUN_COUNT, WALL_TIME); + VmGcStatDAO dao = new VmGcStatDAOImpl(storage); + dao.putVmGcStat(stat); + + verify(storage).putPojo(VmGcStatDAO.vmGcStatCategory, false, stat); + } +} diff -r 0ba74f790a8a -r ceb28ef8f9e8 vm-gc/pom.xml --- a/vm-gc/pom.xml Mon Jan 07 15:50:03 2013 -0500 +++ b/vm-gc/pom.xml Mon Jan 07 15:50:59 2013 -0500 @@ -51,8 +51,10 @@ Thermostat VM GC plugin + agent client-core client-swing + common remote-collector-command remote-collector-client-common remote-collector-client-swing