# HG changeset patch # User Elliott Baron # Date 1357591499 18000 # Node ID 3477dae0e6dadaeff75322e493aabae1c6bab98c # Parent 7765a6857a8d0e1b72d979730b286b610e0a107e Create Host CPU agent and common bundles This first commit, in a series, extracts Host CPU data collection from SystemBackend into a host-cpu-agent bundle. It also moves the CpuStatDAO from common-core into a host-cpu-common bundle that registers the DAO once Storage is available. This also removes the DAO from DAOFactory. One side-effect is changing the visibility of HostLatestPojoListGetter to public in order for this DAO implementation (and DAOs in the other commits in this series) to access it. Reviewed-by: omajid, jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-January/004993.html diff -r 7765a6857a8d -r 3477dae0e6da agent/core/src/main/java/com/redhat/thermostat/utils/SysConf.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/main/java/com/redhat/thermostat/utils/SysConf.java Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,87 @@ +/* + * 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.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * A wrapper over POSIX's sysconf. + *

+ * Implementation notes: uses {@code getconf(1)} + */ +public class SysConf { + + private SysConf() { + /* do not initialize */ + } + + public static long getClockTicksPerSecond() { + String ticks = sysConf("CLK_TCK"); + try { + return Long.valueOf(ticks); + } catch (NumberFormatException nfe) { + return 0; + } + } + + private static String sysConf(String arg) { + BufferedReader reader = null; + try { + Process process = Runtime.getRuntime().exec(new String[] { "getconf", arg }); + int result = process.waitFor(); + if (result != 0) { + return null; + } + reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + return reader.readLine(); + } catch (IOException e) { + return null; + } catch (InterruptedException e) { + return null; + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + // TODO + } + } + } + } +} diff -r 7765a6857a8d -r 3477dae0e6da agent/core/src/test/java/com/redhat/thermostat/utils/SysConfTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/core/src/test/java/com/redhat/thermostat/utils/SysConfTest.java Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,52 @@ +/* + * 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.utils; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.redhat.thermostat.utils.SysConf; + +public class SysConfTest { + + @Test + public void test() { + long ticksPerSecond = SysConf.getClockTicksPerSecond(); + assertTrue(ticksPerSecond >= 1); + } +} diff -r 7765a6857a8d -r 3477dae0e6da common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java --- a/common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java Mon Jan 07 11:50:49 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +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.CpuStat; - -public interface CpuStatDAO extends Countable { - - static Key> cpuLoadKey = new Key<>("perProcessorUsage", false); - - static final Category cpuStatCategory = new Category("cpu-stats", - Key.AGENT_ID, Key.TIMESTAMP, cpuLoadKey); - - List getLatestCpuStats(HostRef ref, long since); - - void putCpuStat(CpuStat stat); - -} diff -r 7765a6857a8d -r 3477dae0e6da common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java --- a/common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java Mon Jan 07 11:50:49 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +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.CpuStat; - -class CpuStatDAOImpl implements CpuStatDAO { - - private final Storage storage; - - private final HostLatestPojoListGetter getter; - - CpuStatDAOImpl(Storage storage) { - this.storage = storage; - storage.registerCategory(cpuStatCategory); - this.getter = new HostLatestPojoListGetter<>(storage, cpuStatCategory, CpuStat.class); - } - - @Override - public List getLatestCpuStats(HostRef ref, long lastTimeStamp) { - return getter.getLatest(ref, lastTimeStamp); - } - - @Override - public void putCpuStat(CpuStat stat) { - storage.putPojo(cpuStatCategory, false, stat); - } - - @Override - public long getCount() { - return storage.getCount(cpuStatCategory); - } -} diff -r 7765a6857a8d -r 3477dae0e6da 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 11:50:49 2013 -0500 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java Mon Jan 07 15:44:59 2013 -0500 @@ -1,5 +1,5 @@ /* - * Copyright 2012 Red Hat, Inc. + * Copyright 2013 Red Hat, Inc. * * This file is part of Thermostat. * @@ -52,8 +52,6 @@ public HostInfoDAO getHostInfoDAO(); - public CpuStatDAO getCpuStatDAO(); - public MemoryStatDAO getMemoryStatDAO(); public NetworkInterfaceInfoDAO getNetworkInterfaceInfoDAO(); diff -r 7765a6857a8d -r 3477dae0e6da 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 11:50:49 2013 -0500 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactoryImpl.java Mon Jan 07 15:44:59 2013 -0500 @@ -1,5 +1,5 @@ /* - * Copyright 2012 Red Hat, Inc. + * Copyright 2013 Red Hat, Inc. * * This file is part of Thermostat. * @@ -57,7 +57,6 @@ private AgentInfoDAO agentDAO; private BackendInfoDAO backendInfoDAO; private HostInfoDAO hostInfoDAO; - private CpuStatDAO cpuStatDAO; private MemoryStatDAO memoryStatDAO; private NetworkInterfaceInfoDAO networkInfoDAO; private VmInfoDAO vmInfoDAO; @@ -99,12 +98,6 @@ } @Override - public CpuStatDAO getCpuStatDAO() { - ensureStorageConnected(); - return cpuStatDAO; - } - - @Override public MemoryStatDAO getMemoryStatDAO() { ensureStorageConnected(); return memoryStatDAO; @@ -168,7 +161,6 @@ registerAndRecordService(HostInfoDAO.class, getHostInfoDAO()); registerAndRecordService(NetworkInterfaceInfoDAO.class, getNetworkInterfaceInfoDAO()); - registerAndRecordService(CpuStatDAO.class, getCpuStatDAO()); registerAndRecordService(MemoryStatDAO.class, getMemoryStatDAO()); registerAndRecordService(VmInfoDAO.class, getVmInfoDAO()); @@ -185,7 +177,6 @@ agentDAO = new AgentInfoDAOImpl(storage); backendInfoDAO = new BackendInfoDAOImpl(storage); hostInfoDAO = new HostInfoDAOImpl(storage, agentDAO); - cpuStatDAO = new CpuStatDAOImpl(storage); memoryStatDAO = new MemoryStatDAOImpl(storage); networkInfoDAO = new NetworkInterfaceInfoDAOImpl(storage); vmInfoDAO = new VmInfoDAOImpl(storage); diff -r 7765a6857a8d -r 3477dae0e6da common/core/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java --- a/common/core/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java Mon Jan 07 11:50:49 2013 -0500 +++ b/common/core/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java Mon Jan 07 15:44:59 2013 -0500 @@ -47,13 +47,13 @@ import com.redhat.thermostat.storage.core.Query.Criteria; import com.redhat.thermostat.storage.model.TimeStampedPojo; -class HostLatestPojoListGetter { +public class HostLatestPojoListGetter { private final Storage storage; private final Category cat; private final Class resultClass; - HostLatestPojoListGetter(Storage storage, Category cat, Class resultClass) { + public HostLatestPojoListGetter(Storage storage, Category cat, Class resultClass) { this.storage = storage; this.cat = cat; this.resultClass = resultClass; diff -r 7765a6857a8d -r 3477dae0e6da common/core/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java --- a/common/core/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java Mon Jan 07 11:50:49 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +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.assertArrayEquals; -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.times; -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 com.redhat.thermostat.storage.core.Category; -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.CpuStat; -import com.redhat.thermostat.test.MockQuery; - -public class CpuStatDAOTest { - - @Test - public void testCategory() { - assertEquals("cpu-stats", CpuStatDAO.cpuStatCategory.getName()); - Collection> keys = CpuStatDAO.cpuStatCategory.getKeys(); - assertTrue(keys.contains(new Key<>("agentId", true))); - assertTrue(keys.contains(new Key("timeStamp", false))); - assertTrue(keys.contains(new Key("perProcessorUsage", false))); - - assertEquals(3, keys.size()); - } - - @Test - public void testGetLatestCpuStats() { - - @SuppressWarnings("unchecked") - Cursor cursor = mock(Cursor.class); - Storage storage = mock(Storage.class); - MockQuery query = new MockQuery(); - HostRef hostRef = mock(HostRef.class); - CpuStatDAO dao = new CpuStatDAOImpl(storage); - - Double LOAD = 5.0; - CpuStat cpuStat = new CpuStat(1234L, new double[] { LOAD }); - - when(cursor.hasNext()).thenReturn(true).thenReturn(false); - when(cursor.next()).thenReturn(cpuStat); - - when(storage.createQuery()).thenReturn(query); - when(storage.findAllPojos(query, CpuStat.class)).thenReturn(cursor); - when(hostRef.getAgentId()).thenReturn("system"); - - List cpuStats = dao.getLatestCpuStats(hostRef, Long.MIN_VALUE); - - assertTrue(query.hasWhereClause(Key.TIMESTAMP, Criteria.GREATER_THAN, Long.MIN_VALUE)); - - assertEquals(1, cpuStats.size()); - CpuStat stat = cpuStats.get(0); - assertEquals(1234L, stat.getTimeStamp()); - assertArrayEquals(new double[] { LOAD }, stat.getPerProcessorUsage(), 0.001); - - } - - @Test - public void testGetLatestCpuStatsTwice() { - - @SuppressWarnings("unchecked") - Cursor cursor = mock(Cursor.class); - Storage storage = mock(Storage.class); - MockQuery query = new MockQuery(); - HostRef hostRef = mock(HostRef.class); - - CpuStatDAO dao = new CpuStatDAOImpl(storage); - - CpuStat cpuStat = new CpuStat(1234L, new double[] { 5.0 }); - - when(cursor.hasNext()).thenReturn(true).thenReturn(false); - when(cursor.next()).thenReturn(cpuStat); - - when(storage.createQuery()).thenReturn(query); - when(storage.findAllPojos(any(Query.class), same(CpuStat.class))).thenReturn(cursor); - when(hostRef.getAgentId()).thenReturn("system"); - - dao.getLatestCpuStats(hostRef, Long.MIN_VALUE); - dao.getLatestCpuStats(hostRef, Long.MIN_VALUE); - - verify(storage, times(2)).findAllPojos(query, CpuStat.class); - - query.hasWhereClauseFor(Key.TIMESTAMP); - } - - @Test - public void testPutCpuStat() { - Storage storage = mock(Storage.class); - CpuStat stat = new CpuStat(1, new double[] {5.0, 10.0, 15.0}); - CpuStatDAO dao = new CpuStatDAOImpl(storage); - dao.putCpuStat(stat); - - verify(storage).putPojo(CpuStatDAO.cpuStatCategory, false, stat); - } - - @Test - public void testGetCount() { - Storage storage = mock(Storage.class); - when(storage.getCount(any(Category.class))).thenReturn(5L); - CpuStatDAO dao = new CpuStatDAOImpl(storage); - Long count = dao.getCount(); - assertEquals((Long) 5L, count); - } -} diff -r 7765a6857a8d -r 3477dae0e6da 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 11:50:49 2013 -0500 +++ b/common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java Mon Jan 07 15:44:59 2013 -0500 @@ -1,5 +1,5 @@ /* - * Copyright 2012 Red Hat, Inc. + * Copyright 2013 Red Hat, Inc. * * This file is part of Thermostat. * @@ -120,12 +120,6 @@ } @Test - public void testGetCpuStatDAO() { - CpuStatDAO dao = daoFactory.getCpuStatDAO(); - assertNotNull(dao); - } - - @Test public void testGetMemoryStatDAO() { MemoryStatDAO dao = daoFactory.getMemoryStatDAO(); assertNotNull(dao); @@ -144,7 +138,7 @@ daoFactory.registerDAOsAndStorageAsOSGiServices(); // currently 12 DAOs and Storage are registered - assertEquals(12, bundleContext.getAllServices().size()); + assertEquals(11, bundleContext.getAllServices().size()); } @Test diff -r 7765a6857a8d -r 3477dae0e6da distribution/config/commands/agent.properties --- a/distribution/config/commands/agent.properties Mon Jan 07 11:50:49 2013 -0500 +++ b/distribution/config/commands/agent.properties Mon Jan 07 15:44:59 2013 -0500 @@ -9,6 +9,8 @@ thermostat-agent-cli-@project.version@.jar, \ thermostat-common-command-@project.version@.jar, \ thermostat-agent-command-@project.version@.jar, \ + thermostat-host-cpu-common-@project.version@.jar, \ + thermostat-host-cpu-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 7765a6857a8d -r 3477dae0e6da distribution/config/commands/gui.properties --- a/distribution/config/commands/gui.properties Mon Jan 07 11:50:49 2013 -0500 +++ b/distribution/config/commands/gui.properties Mon Jan 07 15:44:59 2013 -0500 @@ -14,6 +14,7 @@ thermostat-client-command-@project.version@.jar, \ thermostat-host-overview-client-core-@project.version@.jar, \ thermostat-host-overview-client-swing-@project.version@.jar, \ + thermostat-host-cpu-common-@project.version@.jar, \ thermostat-host-cpu-client-core-@project.version@.jar, \ thermostat-host-cpu-client-swing-@project.version@.jar, \ thermostat-host-memory-client-core-@project.version@.jar, \ diff -r 7765a6857a8d -r 3477dae0e6da distribution/pom.xml --- a/distribution/pom.xml Mon Jan 07 11:50:49 2013 -0500 +++ b/distribution/pom.xml Mon Jan 07 15:44:59 2013 -0500 @@ -372,6 +372,11 @@ com.redhat.thermostat + thermostat-host-cpu-agent + ${project.version} + + + com.redhat.thermostat thermostat-host-memory-client-core ${project.version} diff -r 7765a6857a8d -r 3477dae0e6da eclipse/com.redhat.thermostat.client.feature/feature.xml --- a/eclipse/com.redhat.thermostat.client.feature/feature.xml Mon Jan 07 11:50:49 2013 -0500 +++ b/eclipse/com.redhat.thermostat.client.feature/feature.xml Mon Jan 07 15:44:59 2013 -0500 @@ -182,4 +182,11 @@ version="0.0.0" unpack="false"/> + + diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/agent/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/agent/pom.xml Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,78 @@ + + + 4.0.0 + + thermostat-host-cpu + com.redhat.thermostat + 0.5.0-SNAPSHOT + + thermostat-host-cpu-agent + bundle + Thermostat Host CPU Agent plugin + + + + org.apache.felix + maven-bundle-plugin + true + + + Red Hat, Inc. + com.redhat.thermostat.host.cpu.agent + com.redhat.thermostat.host.cpu.agent.internal.Activator + + com.redhat.thermostat.host.cpu.agent + + + com.redhat.thermostat.host.cpu.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-host-cpu-common + ${project.version} + + + com.redhat.thermostat + thermostat-agent-core + ${project.version} + + + com.redhat.thermostat + thermostat-storage-core + ${project.version} + + + diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/Activator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/Activator.java Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,101 @@ +/* + * 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.host.cpu.agent.internal; + +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +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.host.cpu.common.CpuStatDAO; + +public class Activator implements BundleActivator { + + private ScheduledExecutorService executor; + private MultipleServiceTracker tracker; + private HostCpuBackend backend; + private ServiceRegistration reg; + + @Override + public void start(final BundleContext context) throws Exception { + executor = Executors.newSingleThreadScheduledExecutor(); + + Class[] deps = new Class[] { + BackendService.class, + CpuStatDAO.class + }; + tracker = new MultipleServiceTracker(context, deps, new Action() { + + @Override + public void dependenciesAvailable(Map services) { + CpuStatDAO cpuStatDao = (CpuStatDAO) services.get(CpuStatDAO.class.getName()); + Version version = new Version(context.getBundle()); + backend = new HostCpuBackend(executor, cpuStatDao, 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. + */ + HostCpuBackend getBackend() { + return backend; + } +} diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatBuilder.java Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,135 @@ +/* + * 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.host.cpu.agent.internal; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.Clock; +import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.storage.model.CpuStat; +import com.redhat.thermostat.utils.ProcDataSource; + +public class CpuStatBuilder { + + private static final Logger logger = LoggingUtils.getLogger(CpuStatBuilder.class); + + private final ProcDataSource dataSource; + private final Clock clock; + private final long ticksPerSecond; + + private boolean initialized = false; + + private long[] previousCpuTicks; + private long previousTime; + + public CpuStatBuilder(Clock clock, ProcDataSource dataSource, long ticksPerSecond) { + this.dataSource = dataSource; + this.clock = clock; + this.ticksPerSecond = ticksPerSecond; + } + + public void initialize() { + if (initialized) { + throw new IllegalStateException("already initialized"); + } + + previousTime = clock.getMonotonicTimeNanos(); + previousCpuTicks = getCurrentCpuTicks(); + initialized = true; + } + + public CpuStat build() { + if (!initialized) { + throw new IllegalStateException("not initialized yet"); + } + + long currentRealTime = clock.getRealTimeMillis(); + long currentTime = clock.getMonotonicTimeNanos(); + long[] currentValues = getCurrentCpuTicks(); + + double[] cpuUsage = new double[currentValues.length]; + + double timeDelta = (currentTime - previousTime) * 1E-9; + for (int i = 0; i < currentValues.length; i++) { + long cpuTicksDelta = currentValues[i] - previousCpuTicks[i]; + // 100 as in 100 percent. + cpuUsage[i] = cpuTicksDelta * (100.0 / timeDelta / ticksPerSecond); + } + previousTime = currentTime; + previousCpuTicks = currentValues; + + return new CpuStat(currentRealTime, cpuUsage); + } + + private long[] getCurrentCpuTicks() { + int maxIndex = 0; + long[] values = new long[1]; + try (BufferedReader reader = new BufferedReader(dataSource.getStatReader())) { + String line; + while ((line = reader.readLine()) != null) { + if (!line.startsWith("cpu")) { + continue; + } + String[] parts = line.split("\\s"); + if (!parts[0].matches("cpu\\d+")) { + continue; + } + + int cpuIndex = Integer.valueOf(parts[0].substring("cpu".length())); + if (cpuIndex > maxIndex) { + long[] newValues = new long[cpuIndex+1]; + System.arraycopy(values, 0, newValues, 0, cpuIndex); + values = newValues; + maxIndex = cpuIndex; + } + values[cpuIndex] = Long.valueOf(parts[1]) + Long.valueOf(parts[2]) + Long.valueOf(parts[3]); + } + } catch (IOException e) { + logger.log(Level.WARNING, "error reading stat file", e); + } + + return values; + } + + public boolean isInitialized() { + return initialized; + } + +} diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/HostCpuBackend.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/HostCpuBackend.java Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,126 @@ +/* + * 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.host.cpu.agent.internal; + +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.backend.BackendID; +import com.redhat.thermostat.backend.BackendsProperties; +import com.redhat.thermostat.common.Clock; +import com.redhat.thermostat.common.SystemClock; +import com.redhat.thermostat.common.Version; +import com.redhat.thermostat.host.cpu.common.CpuStatDAO; +import com.redhat.thermostat.utils.ProcDataSource; +import com.redhat.thermostat.utils.SysConf; + +public class HostCpuBackend extends Backend { + + private static final long PROC_CHECK_INTERVAL = 1000; // TODO make this configurable. + + private final CpuStatBuilder cpuStatBuilder; + private CpuStatDAO cpuStats; + private ScheduledExecutorService executor; + private boolean started; + + public HostCpuBackend(ScheduledExecutorService executor, CpuStatDAO cpuStatDAO, Version version) { + super(new BackendID("Host CPU Backend", HostCpuBackend.class.getName())); + this.executor = executor; + this.cpuStats = cpuStatDAO; + + setConfigurationValue(BackendsProperties.VENDOR.name(), "Red Hat, Inc."); + setConfigurationValue(BackendsProperties.DESCRIPTION.name(), "Gathers CPU statistics about a host"); + setConfigurationValue(BackendsProperties.VERSION.name(), version.getVersionNumber()); + + Clock clock = new SystemClock(); + long ticksPerSecond = SysConf.getClockTicksPerSecond(); + ProcDataSource source = new ProcDataSource(); + cpuStatBuilder = new CpuStatBuilder(clock, source, ticksPerSecond); + } + + @Override + public boolean activate() { + if (!started) { + executor.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + if (!cpuStatBuilder.isInitialized()) { + cpuStatBuilder.initialize(); + } else { + cpuStats.putCpuStat(cpuStatBuilder.build()); + } + } + }, 0, PROC_CHECK_INTERVAL, TimeUnit.MILLISECONDS); + started = true; + } + return true; + } + + @Override + public boolean deactivate() { + executor.shutdown(); + started = false; + return true; + } + + @Override + public boolean isActive() { + return started; + } + + @Override + protected void setDAOFactoryAction() { + // No use for DAOFactory + } + + @Override + public String getConfigurationValue(String key) { + return null; + } + + @Override + public boolean attachToNewProcessByDefault() { + return true; + } + + @Override + public int getOrderValue() { + return ORDER_CPU_GROUP; + } + +} diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/ActivatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/ActivatorTest.java Mon Jan 07 15:44: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.host.cpu.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.host.cpu.common.CpuStatDAO; +import com.redhat.thermostat.test.StubBundleContext; + +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); + CpuStatDAO cpuStatDAO = mock(CpuStatDAO.class); + + context.registerService(BackendService.class, service, null); + context.registerService(CpuStatDAO.class, cpuStatDAO, null); + + Activator activator = new Activator(); + + activator.start(context); + + assertTrue(context.isServiceRegistered(Backend.class.getName(), HostCpuBackend.class)); + HostCpuBackend backend = activator.getBackend(); + assertNotNull(backend); + + activator.stop(context); + + assertFalse(backend.isActive()); + + assertEquals(0, context.getServiceListeners().size()); + assertEquals(2, context.getAllServices().size()); + } + +} diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatBuilderTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatBuilderTest.java Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,111 @@ +/* + * 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.host.cpu.agent.internal; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertNotNull; +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.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + +import org.junit.Test; + +import com.redhat.thermostat.common.Clock; +import com.redhat.thermostat.common.SystemClock; +import com.redhat.thermostat.storage.model.CpuStat; +import com.redhat.thermostat.utils.ProcDataSource; + +public class CpuStatBuilderTest { + + @Test + public void testSimpleBuild() { + ProcDataSource dataSource = new ProcDataSource(); + CpuStatBuilder builder= new CpuStatBuilder(new SystemClock(), dataSource, 100l); + builder.initialize(); + CpuStat stat = builder.build(); + assertNotNull(stat); + } + + @Test (expected=IllegalStateException.class) + public void buildWithoutInitializeThrowsException() { + Clock clock = mock(Clock.class); + ProcDataSource dataSource = mock(ProcDataSource.class); + long ticksPerSecond = 1; + CpuStatBuilder builder = new CpuStatBuilder(clock, dataSource, ticksPerSecond); + builder.build(); + } + + @Test + public void testBuildCpuStatFromFile() throws IOException { + long CLOCK1 = 1000; + long CLOCK2 = 2000; + + String firstReadContents = + "cpu 100 0 0 1000 1000\n" + + "cpu0 100 0 0 1000 1000\n" + + "cpu1 10 80 10 1000 1000\n"; + BufferedReader reader1 = new BufferedReader(new StringReader(firstReadContents)); + + String secondReadContents = + "cpu 400 0 0 1000 1000\n" + + "cpu0 200 0 0 1000 1000\n" + + "cpu1 30 50 120 1000 1000\n"; + BufferedReader reader2 = new BufferedReader(new StringReader(secondReadContents)); + + long ticksPerSecond = 100; + Clock clock = mock(Clock.class); + when(clock.getRealTimeMillis()).thenReturn(CLOCK2); + when(clock.getMonotonicTimeNanos()).thenReturn((long)(CLOCK1 * 1E6)).thenReturn((long)(CLOCK2 * 1E6)); + + ProcDataSource dataSource = mock(ProcDataSource.class); + when(dataSource.getStatReader()).thenReturn(reader1).thenReturn(reader2); + CpuStatBuilder builder = new CpuStatBuilder(clock, dataSource, ticksPerSecond); + + builder.initialize(); + + CpuStat stat = builder.build(); + + verify(dataSource, times(2)).getStatReader(); + assertArrayEquals(new double[] {100, 100}, stat.getPerProcessorUsage(), 0.01); + } + +} diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/HostCpuBackendTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/HostCpuBackendTest.java Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,96 @@ +/* + * 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.host.cpu.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.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.redhat.thermostat.common.Version; +import com.redhat.thermostat.host.cpu.common.CpuStatDAO; +import com.redhat.thermostat.storage.model.CpuStat; + +public class HostCpuBackendTest { + + private HostCpuBackend backend; + private ScheduledExecutorService executor; + private CpuStatDAO cpuStatDao; + + @Before + public void setup() { + executor = mock(ScheduledExecutorService.class); + cpuStatDao = mock(CpuStatDAO.class); + Version version = mock(Version.class); + when(version.getVersionNumber()).thenReturn("0.0.0"); + + backend = new HostCpuBackend(executor, cpuStatDao, version); + } + + @Test + public void testActivate() { + backend.activate(); + ArgumentCaptor captor = ArgumentCaptor.forClass(Runnable.class); + verify(executor).scheduleAtFixedRate(captor.capture(), any(Long.class), any(Long.class), any(TimeUnit.class)); + assertTrue(backend.isActive()); + + // Run to ensure working + Runnable runnable = captor.getValue(); + runnable.run(); + verify(cpuStatDao, never()).putCpuStat(any(CpuStat.class)); + runnable.run(); + verify(cpuStatDao).putCpuStat(any(CpuStat.class)); + } + + @Test + public void testDeactivate() { + backend.activate(); + backend.deactivate(); + verify(executor).shutdown(); + assertFalse(backend.isActive()); + } +} diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/client-core/pom.xml --- a/host-cpu/client-core/pom.xml Mon Jan 07 11:50:49 2013 -0500 +++ b/host-cpu/client-core/pom.xml Mon Jan 07 15:44:59 2013 -0500 @@ -62,6 +62,11 @@ com.redhat.thermostat + thermostat-host-cpu-common + ${project.version} + + + com.redhat.thermostat thermostat-client-core ${project.version} diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/HostCpuService.java --- a/host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/HostCpuService.java Mon Jan 07 11:50:49 2013 -0500 +++ b/host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/HostCpuService.java Mon Jan 07 15:44:59 2013 -0500 @@ -41,11 +41,11 @@ 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.CpuStatDAO; import com.redhat.thermostat.common.dao.HostInfoDAO; import com.redhat.thermostat.common.dao.HostRef; import com.redhat.thermostat.common.utils.OSGIUtils; import com.redhat.thermostat.host.cpu.client.core.internal.HostCpuController; +import com.redhat.thermostat.host.cpu.common.CpuStatDAO; public class HostCpuService implements InformationService { diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/Activator.java --- a/host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/Activator.java Mon Jan 07 11:50:49 2013 -0500 +++ b/host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/Activator.java Mon Jan 07 15:44:59 2013 -0500 @@ -50,10 +50,10 @@ 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.CpuStatDAO; import com.redhat.thermostat.common.dao.HostInfoDAO; import com.redhat.thermostat.common.dao.HostRef; import com.redhat.thermostat.host.cpu.client.core.HostCpuService; +import com.redhat.thermostat.host.cpu.common.CpuStatDAO; public class Activator implements BundleActivator { diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuController.java --- a/host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuController.java Mon Jan 07 11:50:49 2013 -0500 +++ b/host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuController.java Mon Jan 07 15:44:59 2013 -0500 @@ -49,13 +49,13 @@ 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.CpuStatDAO; import com.redhat.thermostat.common.dao.HostInfoDAO; import com.redhat.thermostat.common.dao.HostRef; import com.redhat.thermostat.common.locale.Translate; import com.redhat.thermostat.host.cpu.client.core.HostCpuView; import com.redhat.thermostat.host.cpu.client.core.HostCpuViewProvider; import com.redhat.thermostat.host.cpu.client.locale.LocaleResources; +import com.redhat.thermostat.host.cpu.common.CpuStatDAO; import com.redhat.thermostat.storage.model.CpuStat; import com.redhat.thermostat.storage.model.DiscreteTimeData; import com.redhat.thermostat.storage.model.HostInfo; diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/ActivatorTest.java --- a/host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/ActivatorTest.java Mon Jan 07 11:50:49 2013 -0500 +++ b/host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/ActivatorTest.java Mon Jan 07 15:44: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.CpuStatDAO; import com.redhat.thermostat.common.dao.HostInfoDAO; import com.redhat.thermostat.host.cpu.client.core.HostCpuService; +import com.redhat.thermostat.host.cpu.common.CpuStatDAO; import com.redhat.thermostat.test.StubBundleContext; public class ActivatorTest { diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuControllerTest.java --- a/host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuControllerTest.java Mon Jan 07 11:50:49 2013 -0500 +++ b/host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuControllerTest.java Mon Jan 07 15:44:59 2013 -0500 @@ -62,12 +62,12 @@ 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.CpuStatDAO; import com.redhat.thermostat.common.dao.HostInfoDAO; import com.redhat.thermostat.common.dao.HostRef; import com.redhat.thermostat.host.cpu.client.core.HostCpuView; import com.redhat.thermostat.host.cpu.client.core.HostCpuViewProvider; import com.redhat.thermostat.host.cpu.client.core.internal.HostCpuController; +import com.redhat.thermostat.host.cpu.common.CpuStatDAO; import com.redhat.thermostat.storage.model.CpuStat; import com.redhat.thermostat.storage.model.DiscreteTimeData; import com.redhat.thermostat.storage.model.HostInfo; diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/common/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/common/pom.xml Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,68 @@ + + + 4.0.0 + + thermostat-host-cpu + com.redhat.thermostat + 0.5.0-SNAPSHOT + + thermostat-host-cpu-common + bundle + Thermostat Host CPU Common plugin + + + + org.apache.felix + maven-bundle-plugin + true + + + Red Hat, Inc. + com.redhat.thermostat.host.cpu.common + com.redhat.thermostat.host.cpu.common.internal.Activator + + com.redhat.thermostat.host.cpu.common + + + com.redhat.thermostat.host.cpu.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 7765a6857a8d -r 3477dae0e6da host-cpu/common/src/main/java/com/redhat/thermostat/host/cpu/common/CpuStatDAO.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/common/src/main/java/com/redhat/thermostat/host/cpu/common/CpuStatDAO.java Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,58 @@ +/* + * 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.host.cpu.common; + +import java.util.List; + +import com.redhat.thermostat.common.dao.Countable; +import com.redhat.thermostat.common.dao.HostRef; +import com.redhat.thermostat.storage.core.Category; +import com.redhat.thermostat.storage.core.Key; +import com.redhat.thermostat.storage.model.CpuStat; + +public interface CpuStatDAO extends Countable { + + static Key> cpuLoadKey = new Key<>("perProcessorUsage", false); + + static final Category cpuStatCategory = new Category("cpu-stats", + Key.AGENT_ID, Key.TIMESTAMP, cpuLoadKey); + + List getLatestCpuStats(HostRef ref, long since); + + void putCpuStat(CpuStat stat); + +} diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/common/src/main/java/com/redhat/thermostat/host/cpu/common/internal/Activator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/common/src/main/java/com/redhat/thermostat/host/cpu/common/internal/Activator.java Mon Jan 07 15:44: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.host.cpu.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.host.cpu.common.CpuStatDAO; +import com.redhat.thermostat.storage.core.Storage; + +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); + CpuStatDAO cpuStatDao = new CpuStatDAOImpl(storage); + reg = context.registerService(CpuStatDAO.class.getName(), cpuStatDao, 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 7765a6857a8d -r 3477dae0e6da host-cpu/common/src/main/java/com/redhat/thermostat/host/cpu/common/internal/CpuStatDAOImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/common/src/main/java/com/redhat/thermostat/host/cpu/common/internal/CpuStatDAOImpl.java Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,73 @@ +/* + * 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.host.cpu.common.internal; + +import java.util.List; + +import com.redhat.thermostat.common.dao.HostLatestPojoListGetter; +import com.redhat.thermostat.common.dao.HostRef; +import com.redhat.thermostat.host.cpu.common.CpuStatDAO; +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.storage.model.CpuStat; + +class CpuStatDAOImpl implements CpuStatDAO { + + private final Storage storage; + + private final HostLatestPojoListGetter getter; + + CpuStatDAOImpl(Storage storage) { + this.storage = storage; + storage.registerCategory(cpuStatCategory); + this.getter = new HostLatestPojoListGetter<>(storage, cpuStatCategory, CpuStat.class); + } + + @Override + public List getLatestCpuStats(HostRef ref, long lastTimeStamp) { + return getter.getLatest(ref, lastTimeStamp); + } + + @Override + public void putCpuStat(CpuStat stat) { + storage.putPojo(cpuStatCategory, false, stat); + } + + @Override + public long getCount() { + return storage.getCount(cpuStatCategory); + } +} diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/common/src/test/java/com/redhat/thermostat/host/cpu/common/internal/ActivatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/common/src/test/java/com/redhat/thermostat/host/cpu/common/internal/ActivatorTest.java Mon Jan 07 15:44: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.host.cpu.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.host.cpu.common.CpuStatDAO; +import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.test.StubBundleContext; + +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(CpuStatDAO.class.getName(), CpuStatDAOImpl.class)); + + activator.stop(context); + + assertEquals(0, context.getServiceListeners().size()); + assertEquals(1, context.getAllServices().size()); + } + +} diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/common/src/test/java/com/redhat/thermostat/host/cpu/common/internal/CpuStatDAOTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host-cpu/common/src/test/java/com/redhat/thermostat/host/cpu/common/internal/CpuStatDAOTest.java Mon Jan 07 15:44:59 2013 -0500 @@ -0,0 +1,156 @@ +/* + * 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.host.cpu.common.internal; + +import static org.junit.Assert.assertArrayEquals; +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.times; +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 com.redhat.thermostat.common.dao.HostRef; +import com.redhat.thermostat.host.cpu.common.CpuStatDAO; +import com.redhat.thermostat.host.cpu.common.internal.CpuStatDAOImpl; +import com.redhat.thermostat.storage.core.Category; +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.CpuStat; +import com.redhat.thermostat.test.MockQuery; + +public class CpuStatDAOTest { + + @Test + public void testCategory() { + assertEquals("cpu-stats", CpuStatDAO.cpuStatCategory.getName()); + Collection> keys = CpuStatDAO.cpuStatCategory.getKeys(); + assertTrue(keys.contains(new Key<>("agentId", true))); + assertTrue(keys.contains(new Key("timeStamp", false))); + assertTrue(keys.contains(new Key("perProcessorUsage", false))); + + assertEquals(3, keys.size()); + } + + @Test + public void testGetLatestCpuStats() { + + @SuppressWarnings("unchecked") + Cursor cursor = mock(Cursor.class); + Storage storage = mock(Storage.class); + MockQuery query = new MockQuery(); + HostRef hostRef = mock(HostRef.class); + CpuStatDAO dao = new CpuStatDAOImpl(storage); + + Double LOAD = 5.0; + CpuStat cpuStat = new CpuStat(1234L, new double[] { LOAD }); + + when(cursor.hasNext()).thenReturn(true).thenReturn(false); + when(cursor.next()).thenReturn(cpuStat); + + when(storage.createQuery()).thenReturn(query); + when(storage.findAllPojos(query, CpuStat.class)).thenReturn(cursor); + when(hostRef.getAgentId()).thenReturn("system"); + + List cpuStats = dao.getLatestCpuStats(hostRef, Long.MIN_VALUE); + + assertTrue(query.hasWhereClause(Key.TIMESTAMP, Criteria.GREATER_THAN, Long.MIN_VALUE)); + + assertEquals(1, cpuStats.size()); + CpuStat stat = cpuStats.get(0); + assertEquals(1234L, stat.getTimeStamp()); + assertArrayEquals(new double[] { LOAD }, stat.getPerProcessorUsage(), 0.001); + + } + + @Test + public void testGetLatestCpuStatsTwice() { + + @SuppressWarnings("unchecked") + Cursor cursor = mock(Cursor.class); + Storage storage = mock(Storage.class); + MockQuery query = new MockQuery(); + HostRef hostRef = mock(HostRef.class); + + CpuStatDAO dao = new CpuStatDAOImpl(storage); + + CpuStat cpuStat = new CpuStat(1234L, new double[] { 5.0 }); + + when(cursor.hasNext()).thenReturn(true).thenReturn(false); + when(cursor.next()).thenReturn(cpuStat); + + when(storage.createQuery()).thenReturn(query); + when(storage.findAllPojos(any(Query.class), same(CpuStat.class))).thenReturn(cursor); + when(hostRef.getAgentId()).thenReturn("system"); + + dao.getLatestCpuStats(hostRef, Long.MIN_VALUE); + dao.getLatestCpuStats(hostRef, Long.MIN_VALUE); + + verify(storage, times(2)).findAllPojos(query, CpuStat.class); + + query.hasWhereClauseFor(Key.TIMESTAMP); + } + + @Test + public void testPutCpuStat() { + Storage storage = mock(Storage.class); + CpuStat stat = new CpuStat(1, new double[] {5.0, 10.0, 15.0}); + CpuStatDAO dao = new CpuStatDAOImpl(storage); + dao.putCpuStat(stat); + + verify(storage).putPojo(CpuStatDAO.cpuStatCategory, false, stat); + } + + @Test + public void testGetCount() { + Storage storage = mock(Storage.class); + when(storage.getCount(any(Category.class))).thenReturn(5L); + CpuStatDAO dao = new CpuStatDAOImpl(storage); + Long count = dao.getCount(); + assertEquals((Long) 5L, count); + } +} diff -r 7765a6857a8d -r 3477dae0e6da host-cpu/pom.xml --- a/host-cpu/pom.xml Mon Jan 07 11:50:49 2013 -0500 +++ b/host-cpu/pom.xml Mon Jan 07 15:44:59 2013 -0500 @@ -51,6 +51,8 @@ Thermostat Host CPU plugin + agent + common client-core client-swing diff -r 7765a6857a8d -r 3477dae0e6da system-backend/src/main/java/com/redhat/thermostat/backend/system/CpuStatBuilder.java --- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/CpuStatBuilder.java Mon Jan 07 11:50:49 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +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.io.BufferedReader; -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.redhat.thermostat.common.Clock; -import com.redhat.thermostat.common.utils.LoggingUtils; -import com.redhat.thermostat.storage.model.CpuStat; -import com.redhat.thermostat.utils.ProcDataSource; - -public class CpuStatBuilder { - - private static final Logger logger = LoggingUtils.getLogger(CpuStatBuilder.class); - - private final ProcDataSource dataSource; - private final Clock clock; - private final long ticksPerSecond; - - private boolean initialized = false; - - private long[] previousCpuTicks; - private long previousTime; - - public CpuStatBuilder(Clock clock, ProcDataSource dataSource, long ticksPerSecond) { - this.dataSource = dataSource; - this.clock = clock; - this.ticksPerSecond = ticksPerSecond; - } - - public void initialize() { - if (initialized) { - throw new IllegalStateException("already initialized"); - } - - previousTime = clock.getMonotonicTimeNanos(); - previousCpuTicks = getCurrentCpuTicks(); - initialized = true; - } - - public CpuStat build() { - if (!initialized) { - throw new IllegalStateException("not initialized yet"); - } - - long currentRealTime = clock.getRealTimeMillis(); - long currentTime = clock.getMonotonicTimeNanos(); - long[] currentValues = getCurrentCpuTicks(); - - double[] cpuUsage = new double[currentValues.length]; - - double timeDelta = (currentTime - previousTime) * 1E-9; - for (int i = 0; i < currentValues.length; i++) { - long cpuTicksDelta = currentValues[i] - previousCpuTicks[i]; - // 100 as in 100 percent. - cpuUsage[i] = cpuTicksDelta * (100.0 / timeDelta / ticksPerSecond); - } - previousTime = currentTime; - previousCpuTicks = currentValues; - - return new CpuStat(currentRealTime, cpuUsage); - } - - private long[] getCurrentCpuTicks() { - int maxIndex = 0; - long[] values = new long[1]; - try (BufferedReader reader = new BufferedReader(dataSource.getStatReader())) { - String line; - while ((line = reader.readLine()) != null) { - if (!line.startsWith("cpu")) { - continue; - } - String[] parts = line.split("\\s"); - if (!parts[0].matches("cpu\\d+")) { - continue; - } - - int cpuIndex = Integer.valueOf(parts[0].substring("cpu".length())); - if (cpuIndex > maxIndex) { - long[] newValues = new long[cpuIndex+1]; - System.arraycopy(values, 0, newValues, 0, cpuIndex); - values = newValues; - maxIndex = cpuIndex; - } - values[cpuIndex] = Long.valueOf(parts[1]) + Long.valueOf(parts[2]) + Long.valueOf(parts[3]); - } - } catch (IOException e) { - logger.log(Level.WARNING, "error reading stat file", e); - } - - return values; - } - - public boolean isInitialized() { - return initialized; - } - -} diff -r 7765a6857a8d -r 3477dae0e6da system-backend/src/main/java/com/redhat/thermostat/backend/system/SysConf.java --- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/SysConf.java Mon Jan 07 11:50:49 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +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.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -/** - * A wrapper over POSIX's sysconf. - *

- * Implementation notes: uses {@code getconf(1)} - */ -public class SysConf { - - private SysConf() { - /* do not initialize */ - } - - public static long getClockTicksPerSecond() { - String ticks = sysConf("CLK_TCK"); - try { - return Long.valueOf(ticks); - } catch (NumberFormatException nfe) { - return 0; - } - } - - private static String sysConf(String arg) { - BufferedReader reader = null; - try { - Process process = Runtime.getRuntime().exec(new String[] { "getconf", arg }); - int result = process.waitFor(); - if (result != 0) { - return null; - } - reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - return reader.readLine(); - } catch (IOException e) { - return null; - } catch (InterruptedException e) { - return null; - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - // TODO - } - } - } - } -} diff -r 7765a6857a8d -r 3477dae0e6da 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 11:50:49 2013 -0500 +++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java Mon Jan 07 15:44:59 2013 -0500 @@ -1,5 +1,5 @@ /* - * Copyright 2012 Red Hat, Inc. + * Copyright 2013 Red Hat, Inc. * * This file is part of Thermostat. * @@ -55,7 +55,6 @@ import com.redhat.thermostat.backend.BackendsProperties; import com.redhat.thermostat.common.Clock; import com.redhat.thermostat.common.SystemClock; -import com.redhat.thermostat.common.dao.CpuStatDAO; import com.redhat.thermostat.common.dao.HostInfoDAO; import com.redhat.thermostat.common.dao.MemoryStatDAO; import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO; @@ -64,12 +63,12 @@ import com.redhat.thermostat.storage.model.NetworkInterfaceInfo; import com.redhat.thermostat.storage.model.VmCpuStat; import com.redhat.thermostat.utils.ProcDataSource; +import com.redhat.thermostat.utils.SysConf; public class SystemBackend extends Backend implements JvmStatusNotifier, JvmStatusListener { private static final Logger logger = LoggingUtils.getLogger(SystemBackend.class); - private CpuStatDAO cpuStats; private HostInfoDAO hostInfos; private MemoryStatDAO memoryStats; private VmCpuStatDAO vmCpuStats; @@ -87,7 +86,6 @@ private final VmCpuStatBuilder vmCpuBuilder; private final HostInfoBuilder hostInfoBuilder; - private final CpuStatBuilder cpuStatBuilder; private final MemoryStatBuilder memoryStatBuilder; public SystemBackend() { @@ -95,14 +93,13 @@ setConfigurationValue(BackendsProperties.VENDOR.name(), "Red Hat, Inc."); setConfigurationValue(BackendsProperties.DESCRIPTION.name(), "Gathers basic information from the system"); - setConfigurationValue(BackendsProperties.VERSION.name(), "0.1.0"); + setConfigurationValue(BackendsProperties.VERSION.name(), "0.5.0"); Clock clock = new SystemClock(); ProcessStatusInfoBuilder builder = new ProcessStatusInfoBuilder(new ProcDataSource()); long ticksPerSecond = SysConf.getClockTicksPerSecond(); ProcDataSource source = new ProcDataSource(); hostInfoBuilder = new HostInfoBuilder(source); - cpuStatBuilder = new CpuStatBuilder(clock, source, ticksPerSecond); memoryStatBuilder = new MemoryStatBuilder(source); int cpuCount = hostInfoBuilder.getCpuInfo().count; @@ -111,7 +108,6 @@ @Override protected void setDAOFactoryAction() { - cpuStats = df.getCpuStatDAO(); hostInfos = df.getHostInfoDAO(); memoryStats = df.getMemoryStatDAO(); vmCpuStats = df.getVmCpuStatDAO(); @@ -139,11 +135,6 @@ timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { - if (!cpuStatBuilder.isInitialized()) { - cpuStatBuilder.initialize(); - } else { - cpuStats.putCpuStat(cpuStatBuilder.build()); - } for (NetworkInterfaceInfo info: NetworkInfoBuilder.build()) { networkInterfaces.putNetworkInterfaceInfo(info); } diff -r 7765a6857a8d -r 3477dae0e6da system-backend/src/test/java/com/redhat/thermostat/backend/system/CpuStatBuilderTest.java --- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/CpuStatBuilderTest.java Mon Jan 07 11:50:49 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +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 static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertNotNull; -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.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; - -import org.junit.Test; - -import com.redhat.thermostat.common.Clock; -import com.redhat.thermostat.common.SystemClock; -import com.redhat.thermostat.common.utils.ArrayUtils; -import com.redhat.thermostat.storage.model.CpuStat; -import com.redhat.thermostat.utils.ProcDataSource; - -public class CpuStatBuilderTest { - - @Test - public void testSimpleBuild() { - ProcDataSource dataSource = new ProcDataSource(); - CpuStatBuilder builder= new CpuStatBuilder(new SystemClock(), dataSource, 100l); - builder.initialize(); - CpuStat stat = builder.build(); - assertNotNull(stat); - } - - @Test (expected=IllegalStateException.class) - public void buildWithoutInitializeThrowsException() { - Clock clock = mock(Clock.class); - ProcDataSource dataSource = mock(ProcDataSource.class); - long ticksPerSecond = 1; - CpuStatBuilder builder = new CpuStatBuilder(clock, dataSource, ticksPerSecond); - builder.build(); - } - - @Test - public void testBuildCpuStatFromFile() throws IOException { - long CLOCK1 = 1000; - long CLOCK2 = 2000; - - String firstReadContents = - "cpu 100 0 0 1000 1000\n" + - "cpu0 100 0 0 1000 1000\n" + - "cpu1 10 80 10 1000 1000\n"; - BufferedReader reader1 = new BufferedReader(new StringReader(firstReadContents)); - - String secondReadContents = - "cpu 400 0 0 1000 1000\n" + - "cpu0 200 0 0 1000 1000\n" + - "cpu1 30 50 120 1000 1000\n"; - BufferedReader reader2 = new BufferedReader(new StringReader(secondReadContents)); - - long ticksPerSecond = 100; - Clock clock = mock(Clock.class); - when(clock.getRealTimeMillis()).thenReturn(CLOCK2); - when(clock.getMonotonicTimeNanos()).thenReturn((long)(CLOCK1 * 1E6)).thenReturn((long)(CLOCK2 * 1E6)); - - ProcDataSource dataSource = mock(ProcDataSource.class); - when(dataSource.getStatReader()).thenReturn(reader1).thenReturn(reader2); - CpuStatBuilder builder = new CpuStatBuilder(clock, dataSource, ticksPerSecond); - - builder.initialize(); - - CpuStat stat = builder.build(); - - verify(dataSource, times(2)).getStatReader(); - assertArrayEquals(new double[] {100, 100}, stat.getPerProcessorUsage(), 0.01); - } - -} diff -r 7765a6857a8d -r 3477dae0e6da system-backend/src/test/java/com/redhat/thermostat/backend/system/SysConfTest.java --- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/SysConfTest.java Mon Jan 07 11:50:49 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +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 static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class SysConfTest { - - @Test - public void test() { - long ticksPerSecond = SysConf.getClockTicksPerSecond(); - assertTrue(ticksPerSecond >= 1); - } -} diff -r 7765a6857a8d -r 3477dae0e6da system-backend/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java --- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java Mon Jan 07 11:50:49 2013 -0500 +++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java Mon Jan 07 15:44:59 2013 -0500 @@ -1,5 +1,5 @@ /* - * Copyright 2012 Red Hat, Inc. + * Copyright 2013 Red Hat, Inc. * * This file is part of Thermostat. * @@ -44,7 +44,6 @@ import org.junit.Before; import org.junit.Test; -import com.redhat.thermostat.common.dao.CpuStatDAO; import com.redhat.thermostat.common.dao.DAOFactory; import com.redhat.thermostat.common.dao.HostInfoDAO; import com.redhat.thermostat.common.dao.MemoryStatDAO; @@ -59,14 +58,12 @@ @Before public void setUp() { Storage s = mock(Storage.class); - CpuStatDAO cDAO = mock(CpuStatDAO.class); HostInfoDAO hDAO = mock(HostInfoDAO.class); MemoryStatDAO mDAO = mock(MemoryStatDAO.class); VmCpuStatDAO vDAO = mock(VmCpuStatDAO.class); NetworkInterfaceInfoDAO nDAO = mock(NetworkInterfaceInfoDAO.class); DAOFactory df = mock(DAOFactory.class); when(df.getStorage()).thenReturn(s); - when(df.getCpuStatDAO()).thenReturn(cDAO); when(df.getHostInfoDAO()).thenReturn(hDAO); when(df.getMemoryStatDAO()).thenReturn(mDAO); when(df.getVmCpuStatDAO()).thenReturn(vDAO);