changeset 891:3477dae0e6da

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
author Elliott Baron <ebaron@redhat.com>
date Mon, 07 Jan 2013 15:44:59 -0500
parents 7765a6857a8d
children 4c8a876b9dc0
files agent/core/src/main/java/com/redhat/thermostat/utils/SysConf.java agent/core/src/test/java/com/redhat/thermostat/utils/SysConfTest.java common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java common/core/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java common/core/src/main/java/com/redhat/thermostat/common/dao/DAOFactoryImpl.java common/core/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java common/core/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java common/core/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java distribution/config/commands/agent.properties distribution/config/commands/gui.properties distribution/pom.xml eclipse/com.redhat.thermostat.client.feature/feature.xml host-cpu/agent/pom.xml host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/Activator.java host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatBuilder.java host-cpu/agent/src/main/java/com/redhat/thermostat/host/cpu/agent/internal/HostCpuBackend.java host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/ActivatorTest.java host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/CpuStatBuilderTest.java host-cpu/agent/src/test/java/com/redhat/thermostat/host/cpu/agent/internal/HostCpuBackendTest.java host-cpu/client-core/pom.xml host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/HostCpuService.java host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/Activator.java host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuController.java host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/ActivatorTest.java host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuControllerTest.java host-cpu/common/pom.xml host-cpu/common/src/main/java/com/redhat/thermostat/host/cpu/common/CpuStatDAO.java host-cpu/common/src/main/java/com/redhat/thermostat/host/cpu/common/internal/Activator.java host-cpu/common/src/main/java/com/redhat/thermostat/host/cpu/common/internal/CpuStatDAOImpl.java host-cpu/common/src/test/java/com/redhat/thermostat/host/cpu/common/internal/ActivatorTest.java host-cpu/common/src/test/java/com/redhat/thermostat/host/cpu/common/internal/CpuStatDAOTest.java host-cpu/pom.xml system-backend/src/main/java/com/redhat/thermostat/backend/system/CpuStatBuilder.java system-backend/src/main/java/com/redhat/thermostat/backend/system/SysConf.java system-backend/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java system-backend/src/test/java/com/redhat/thermostat/backend/system/CpuStatBuilderTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/SysConfTest.java system-backend/src/test/java/com/redhat/thermostat/backend/system/SystemBackendTest.java
diffstat 39 files changed, 1445 insertions(+), 707 deletions(-) [+]
line wrap: on
line diff
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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.
+ * <p>
+ * 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
+                }
+            }
+        }
+    }
+}
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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);
+    }
+}
--- 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
- * <http://www.gnu.org/licenses/>.
- *
- * 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<List<Double>> cpuLoadKey = new Key<>("perProcessorUsage", false);
-
-    static final Category cpuStatCategory = new Category("cpu-stats",
-            Key.AGENT_ID, Key.TIMESTAMP, cpuLoadKey);
-
-    List<CpuStat> getLatestCpuStats(HostRef ref, long since);
-
-    void putCpuStat(CpuStat stat);
-
-}
--- 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
- * <http://www.gnu.org/licenses/>.
- *
- * 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<CpuStat> getter;
-
-    CpuStatDAOImpl(Storage storage) {
-        this.storage = storage;
-        storage.registerCategory(cpuStatCategory);
-        this.getter = new HostLatestPojoListGetter<>(storage, cpuStatCategory, CpuStat.class);
-    }
-
-    @Override
-    public List<CpuStat> 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);
-    }
-}
--- 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();
--- 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);
--- 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<T extends TimeStampedPojo> {
+public class HostLatestPojoListGetter<T extends TimeStampedPojo> {
 
     private final Storage storage;
     private final Category cat;
     private final Class<T> resultClass;
 
-    HostLatestPojoListGetter(Storage storage, Category cat, Class<T> resultClass) {
+    public HostLatestPojoListGetter(Storage storage, Category cat, Class<T> resultClass) {
         this.storage = storage;
         this.cat = cat;
         this.resultClass = resultClass;
--- 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
- * <http://www.gnu.org/licenses/>.
- *
- * 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<Key<?>> keys = CpuStatDAO.cpuStatCategory.getKeys();
-        assertTrue(keys.contains(new Key<>("agentId", true)));
-        assertTrue(keys.contains(new Key<Long>("timeStamp", false)));
-        assertTrue(keys.contains(new Key<Double>("perProcessorUsage", false)));
-
-        assertEquals(3, keys.size());
-    }
-
-    @Test
-    public void testGetLatestCpuStats() {
-
-        @SuppressWarnings("unchecked")
-        Cursor<CpuStat> 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<CpuStat> 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<CpuStat> 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);
-    }
-}
--- 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
--- 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, \
--- 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, \
--- 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 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-host-cpu-agent</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
       <artifactId>thermostat-host-memory-client-core</artifactId>
       <version>${project.version}</version>
     </dependency>
--- 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"/>
 
+   <plugin
+         id="com.redhat.thermostat.host.cpu.common"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
 </feature>
--- /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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>thermostat-host-cpu</artifactId>
+    <groupId>com.redhat.thermostat</groupId>
+    <version>0.5.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>thermostat-host-cpu-agent</artifactId>
+  <packaging>bundle</packaging>
+  <name>Thermostat Host CPU Agent plugin</name>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-SymbolicName>com.redhat.thermostat.host.cpu.agent</Bundle-SymbolicName>
+            <Bundle-Activator>com.redhat.thermostat.host.cpu.agent.internal.Activator</Bundle-Activator>
+            <Export-Package>
+              com.redhat.thermostat.host.cpu.agent
+            </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.host.cpu.agent.internal
+            </Private-Package>
+            <!-- Do not autogenerate uses clauses in Manifests -->
+            <_nouses>true</_nouses>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-host-cpu-common</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-agent-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-storage-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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<String, Object> 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;
+    }
+}
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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;
+    }
+
+}
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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;
+    }
+
+}
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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());
+    }
+
+}
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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);
+    }
+
+}
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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<Runnable> 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());
+    }
+}
--- 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 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-host-cpu-common</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
       <artifactId>thermostat-client-core</artifactId>
       <version>${project.version}</version>
     </dependency>
--- 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<HostRef> {
     
--- 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 {
     
--- 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;
--- 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 {
--- 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;
--- /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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>thermostat-host-cpu</artifactId>
+    <groupId>com.redhat.thermostat</groupId>
+    <version>0.5.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>thermostat-host-cpu-common</artifactId>
+  <packaging>bundle</packaging>
+  <name>Thermostat Host CPU Common plugin</name>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-SymbolicName>com.redhat.thermostat.host.cpu.common</Bundle-SymbolicName>
+            <Bundle-Activator>com.redhat.thermostat.host.cpu.common.internal.Activator</Bundle-Activator>
+            <Export-Package>
+              com.redhat.thermostat.host.cpu.common
+            </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.host.cpu.common.internal
+            </Private-Package>
+            <!-- Do not autogenerate uses clauses in Manifests -->
+            <_nouses>true</_nouses>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-storage-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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<List<Double>> cpuLoadKey = new Key<>("perProcessorUsage", false);
+
+    static final Category cpuStatCategory = new Category("cpu-stats",
+            Key.AGENT_ID, Key.TIMESTAMP, cpuLoadKey);
+
+    List<CpuStat> getLatestCpuStats(HostRef ref, long since);
+
+    void putCpuStat(CpuStat stat);
+
+}
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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();
+    }
+
+}
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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<CpuStat> getter;
+
+    CpuStatDAOImpl(Storage storage) {
+        this.storage = storage;
+        storage.registerCategory(cpuStatCategory);
+        this.getter = new HostLatestPojoListGetter<>(storage, cpuStatCategory, CpuStat.class);
+    }
+
+    @Override
+    public List<CpuStat> 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);
+    }
+}
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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());
+    }
+
+}
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ * 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<Key<?>> keys = CpuStatDAO.cpuStatCategory.getKeys();
+        assertTrue(keys.contains(new Key<>("agentId", true)));
+        assertTrue(keys.contains(new Key<Long>("timeStamp", false)));
+        assertTrue(keys.contains(new Key<Double>("perProcessorUsage", false)));
+
+        assertEquals(3, keys.size());
+    }
+
+    @Test
+    public void testGetLatestCpuStats() {
+
+        @SuppressWarnings("unchecked")
+        Cursor<CpuStat> 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<CpuStat> 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<CpuStat> 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);
+    }
+}
--- 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 @@
   <name>Thermostat Host CPU plugin</name>
 
   <modules>
+    <module>agent</module>
+    <module>common</module>
     <module>client-core</module>
     <module>client-swing</module>
   </modules>
--- 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
- * <http://www.gnu.org/licenses/>.
- *
- * 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;
-    }
-
-}
--- 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
- * <http://www.gnu.org/licenses/>.
- *
- * 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.
- * <p>
- * 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
-                }
-            }
-        }
-    }
-}
--- 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);
                 }
--- 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
- * <http://www.gnu.org/licenses/>.
- *
- * 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);
-    }
-
-}
--- 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
- * <http://www.gnu.org/licenses/>.
- *
- * 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);
-    }
-}
--- 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);