changeset 192:7630545a635f

Change DAO arguments from constructor to getter and generalize getLatestFOO() methods reviewed-by: rkennke review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-March/000580.html
author Jon VanAlten <jon.vanalten@redhat.com>
date Tue, 03 Apr 2012 10:22:17 -0400
parents 4a33f41c7782
children b72444696129
files agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmClassListener.java agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java agent/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java client/src/main/java/com/redhat/thermostat/client/ui/HostCpuController.java client/src/main/java/com/redhat/thermostat/client/ui/HostMemoryController.java client/src/main/java/com/redhat/thermostat/client/ui/HostOverviewController.java client/src/main/java/com/redhat/thermostat/client/ui/VmClassStatController.java client/src/main/java/com/redhat/thermostat/client/ui/VmCpuController.java client/src/main/java/com/redhat/thermostat/client/ui/VmGcController.java client/src/main/java/com/redhat/thermostat/client/ui/VmMemoryController.java client/src/main/java/com/redhat/thermostat/client/ui/VmOverviewController.java client/src/test/java/com/redhat/thermostat/client/VmClassStatControllerTest.java client/src/test/java/com/redhat/thermostat/client/appctx/ApplicationContextUtil.java client/src/test/java/com/redhat/thermostat/client/ui/HostCpuControllerTest.java client/src/test/java/com/redhat/thermostat/client/ui/HostMemoryControllerTest.java client/src/test/java/com/redhat/thermostat/client/ui/VmCpuControllerTest.java common/src/main/java/com/redhat/thermostat/common/dao/Converter.java common/src/main/java/com/redhat/thermostat/common/dao/CpuStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java common/src/main/java/com/redhat/thermostat/common/dao/HostInfoConverter.java common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java common/src/main/java/com/redhat/thermostat/common/dao/LatestPojoListGetter.java common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverter.java common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAO.java common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/VmInfoConverter.java common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAO.java common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetter.java common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/model/CpuStat.java common/src/main/java/com/redhat/thermostat/common/model/HostInfo.java common/src/main/java/com/redhat/thermostat/common/model/MemoryStat.java common/src/main/java/com/redhat/thermostat/common/model/NetworkInterfaceInfo.java common/src/main/java/com/redhat/thermostat/common/model/Pojo.java common/src/main/java/com/redhat/thermostat/common/model/TimeStampedPojo.java common/src/main/java/com/redhat/thermostat/common/model/VmClassStat.java common/src/main/java/com/redhat/thermostat/common/model/VmCpuStat.java common/src/main/java/com/redhat/thermostat/common/model/VmGcStat.java common/src/main/java/com/redhat/thermostat/common/model/VmInfo.java common/src/main/java/com/redhat/thermostat/common/model/VmMemoryStat.java common/src/main/java/com/redhat/thermostat/common/storage/Key.java common/src/test/java/com/redhat/thermostat/common/dao/CpuStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/HostInfoConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/HostInfoDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetterTest.java common/src/test/java/com/redhat/thermostat/common/dao/MemoryStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/MemoryStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmInfoConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmInfoDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOTest.java
diffstat 83 files changed, 808 insertions(+), 415 deletions(-) [+]
line wrap: on
line diff
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatHostListener.java	Tue Apr 03 10:22:17 2012 -0400
@@ -129,7 +129,7 @@
                         extractor.getMainClass(), extractor.getCommandLine(),
                         extractor.getVmName(), extractor.getVmInfo(), extractor.getVmVersion(), extractor.getVmArguments(),
                         properties, environment, loadedNativeLibraries);
-                backend.store(new VmInfoConverter().vmInfoToChunk(info));
+                backend.store(new VmInfoConverter().toChunk(info));
                 logger.finer("Sent VM_STARTED messsage");
             } catch (MonitorException me) {
                 logger.log(Level.WARNING, "error getting vm info for " + vmId, me);
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmClassListener.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmClassListener.java	Tue Apr 03 10:22:17 2012 -0400
@@ -80,7 +80,7 @@
             long timestamp = System.currentTimeMillis();
             VmClassStat stat = new VmClassStat(vmId, timestamp, loadedClasses);
             VmClassStatConverter dao = new VmClassStatConverter();
-            backend.store(dao.vmClassStatToChunk(stat));
+            backend.store(dao.toChunk(stat));
         } catch (MonitorException e) {
             logger.log(Level.WARNING, "error gathering class info for vm " + vmId, e);
         }
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java	Tue Apr 03 10:22:17 2012 -0400
@@ -97,7 +97,7 @@
                         extractor.getCollectorName(i),
                         extractor.getCollectorInvocations(i),
                         extractor.getCollectorTime(i));
-                backend.store(new VmGcStatConverter().vmGcStatToChunk(stat));
+                backend.store(new VmGcStatConverter().toChunk(stat));
             }
         } catch (MonitorException e) {
             logger.log(Level.WARNING, "error gathering gc info for vm " + vmId, e);
@@ -132,7 +132,7 @@
                     s.used = extractor.getSpaceUsed(generation, space);
                 }
             }
-            backend.store(new VmMemoryStatConverter().vmMemoryStatToChunk(stat));
+            backend.store(new VmMemoryStatConverter().toChunk(stat));
         } catch (MonitorException e) {
             logger.log(Level.WARNING, "error gathering memory info for vm " + vmId, e);
         }
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/agent/src/main/java/com/redhat/thermostat/backend/system/SystemBackend.java	Tue Apr 03 10:22:17 2012 -0400
@@ -123,22 +123,22 @@
         if (!getObserveNewJvm()) {
             logger.fine("not monitoring new vms");
         }
-        store(new HostInfoConverter().hostInfoToChunk(new HostInfoBuilder(new ProcDataSource()).build()));
+        store(new HostInfoConverter().toChunk(new HostInfoBuilder(new ProcDataSource()).build()));
 
         timer = new Timer();
         timer.scheduleAtFixedRate(new TimerTask() {
             @Override
             public void run() {
                 ProcDataSource dataSource = new ProcDataSource();
-                store(new CpuStatConverter().cpuStatToChunk(new CpuStatBuilder(dataSource).build()));
+                store(new CpuStatConverter().toChunk(new CpuStatBuilder(dataSource).build()));
                 for (NetworkInterfaceInfo info: NetworkInfoBuilder.build()) {
-                    store(new NetworkInterfaceInfoConverter().networkInfoToChunk(info));
+                    store(new NetworkInterfaceInfoConverter().toChunk(info));
                 }
-                store(new MemoryStatConverter().memoryStatToChunk(new MemoryStatBuilder(dataSource).build()));
+                store(new MemoryStatConverter().toChunk(new MemoryStatBuilder(dataSource).build()));
 
                 for (Integer pid : pidsToMonitor) {
                     if (vmCpuBuilder.knowsAbout(pid)) {
-                        store(new VmCpuStatConverter().vmCpuStatToChunk(vmCpuBuilder.build(pid)));
+                        store(new VmCpuStatConverter().toChunk(vmCpuBuilder.build(pid)));
                     } else {
                         vmCpuBuilder.learnAbout(pid);
                     }
--- a/client/src/main/java/com/redhat/thermostat/client/ui/HostCpuController.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/HostCpuController.java	Tue Apr 03 10:22:17 2012 -0400
@@ -60,13 +60,15 @@
 
     private final HostInfoDAO hostInfoDAO;
     private final CpuStatDAO cpuStatDAO;
+    private final HostRef ref;
 
     public HostCpuController(HostRef ref) {
+        this.ref = ref;
         view = createView();
         view.clearCpuLoadData();
         DAOFactory daos = ApplicationContext.getInstance().getDAOFactory();
-        hostInfoDAO = daos.getHostInfoDAO(ref);
-        cpuStatDAO = daos.getCpuStatDAO(ref);
+        hostInfoDAO = daos.getHostInfoDAO();
+        cpuStatDAO = daos.getCpuStatDAO();
 
         backgroundUpdateTimer = ApplicationContext.getInstance().getTimerFactory().createTimer();
         backgroundUpdateTimer.setAction(new Runnable() {
@@ -85,7 +87,7 @@
 
     // TODO: Consider doing this in a background thread (move to view and use SwingWorker or such).
     private void updateView() {
-        HostInfo hostInfo = hostInfoDAO.getHostInfo();
+        HostInfo hostInfo = hostInfoDAO.getHostInfo(ref);
 
         view.setCpuCount(String.valueOf(hostInfo.getCpuCount()));
         view.setCpuModel(hostInfo.getCpuModel());
@@ -104,7 +106,7 @@
     }
 
     private void doCpuChartUpdate() {
-        List<CpuStat> cpuStats = cpuStatDAO.getLatestCpuStats();
+        List<CpuStat> cpuStats = cpuStatDAO.getLatestCpuStats(ref);
         List<DiscreteTimeData<Double>> result = new ArrayList<DiscreteTimeData<Double>>();
         for (CpuStat stat : cpuStats) {
             result.add(new DiscreteTimeData<Double>(stat.getTimeStamp(), stat.getLoad5()));
--- a/client/src/main/java/com/redhat/thermostat/client/ui/HostMemoryController.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/HostMemoryController.java	Tue Apr 03 10:22:17 2012 -0400
@@ -63,14 +63,16 @@
 
     private final HostInfoDAO hostInfoDAO;
     private final MemoryStatDAO memoryStatDAO;
+    private final HostRef ref;
 
     private final Timer backgroundUpdateTimer;
     private final GraphVisibilityChangeListener listener = new ShowHideGraph();
 
-    public HostMemoryController(HostRef hostRef) {
+    public HostMemoryController(HostRef ref) {
+        this.ref = ref;
         DAOFactory daos = ApplicationContext.getInstance().getDAOFactory();
-        hostInfoDAO = daos.getHostInfoDAO(hostRef);
-        memoryStatDAO = daos.getMemoryStatDAO(hostRef);
+        hostInfoDAO = daos.getHostInfoDAO();
+        memoryStatDAO = daos.getMemoryStatDAO();
 
         view = createView();
 
@@ -95,7 +97,7 @@
         backgroundUpdateTimer.scheduleAtFixedRate(new TimerTask() {
             @Override
             public void run() {
-                view.setTotalMemory(String.valueOf(hostInfoDAO.getHostInfo().getTotalMemory()));
+                view.setTotalMemory(String.valueOf(hostInfoDAO.getHostInfo(ref).getTotalMemory()));
                 doMemoryChartUpdate();
             }
 
@@ -127,7 +129,7 @@
         List<DiscreteTimeData<? extends Number>> swapTotal = new LinkedList<>();
         List<DiscreteTimeData<? extends Number>> swapFree = new LinkedList<>();
         
-        for (MemoryStat stat : memoryStatDAO.getLatestMemoryStats()) {
+        for (MemoryStat stat : memoryStatDAO.getLatestMemoryStats(ref)) {
             long timeStamp = stat.getTimeStamp();
             memFree.add(new DiscreteTimeData<Long>(timeStamp, stat.getFree()));
             memTotal.add(new DiscreteTimeData<Long>(timeStamp, stat.getTotal()));
--- a/client/src/main/java/com/redhat/thermostat/client/ui/HostOverviewController.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/HostOverviewController.java	Tue Apr 03 10:22:17 2012 -0400
@@ -66,7 +66,7 @@
 
     private static final Logger logger = LoggingUtils.getLogger(HostOverviewController.class);
 
-    private final HostRef hostRef;
+    private final HostRef ref;
     private final HostInfoDAO hostInfoDAO;
     private final NetworkInterfaceInfoDAO networkInfoDAO;
 
@@ -75,10 +75,10 @@
     private final HostOverviewView view;
 
     public HostOverviewController(HostRef ref) {
-        this.hostRef = ref;
+        this.ref = ref;
         DAOFactory df = ApplicationContext.getInstance().getDAOFactory();
-        hostInfoDAO = df.getHostInfoDAO(hostRef);
-        networkInfoDAO = df.getNetworkInterfaceInfoDAO(hostRef);
+        hostInfoDAO = df.getHostInfoDAO();
+        networkInfoDAO = df.getNetworkInterfaceInfoDAO();
 
         final Vector<String> networkTableColumnVector;
         networkTableColumnVector = new Vector<String>();
@@ -104,7 +104,7 @@
 
         @Override
         protected List<NetworkInterfaceInfo> doInBackground() throws Exception {
-            return networkInfoDAO.getNetworkInterfaces();
+            return networkInfoDAO.getNetworkInterfaces(ref);
         }
 
         @Override
@@ -137,7 +137,7 @@
         backgroundUpdateTimer.scheduleAtFixedRate(new TimerTask() {
             @Override
             public void run() {
-                HostInfo hostInfo = hostInfoDAO.getHostInfo();
+                HostInfo hostInfo = hostInfoDAO.getHostInfo(ref);
                 view.setHostName(hostInfo.getHostname());
                 view.setOsName(hostInfo.getOsName());
                 view.setOsKernel(hostInfo.getOsKernel());
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmClassStatController.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmClassStatController.java	Tue Apr 03 10:22:17 2012 -0400
@@ -55,10 +55,10 @@
     private class UpdateChartData extends TimerTask {
         @Override
         public void run() {
-            List<VmClassStat> latestClassStats = dao.getLatestClassStats();
+            List<VmClassStat> latestClassStats = dao.getLatestClassStats(ref);
             List<DiscreteTimeData<Long>> timeData = new ArrayList<>();
             for (VmClassStat stat : latestClassStats) {
-                timeData.add(new DiscreteTimeData<Long>(stat.getTimestamp(), stat.getLoadedClasses()));
+                timeData.add(new DiscreteTimeData<Long>(stat.getTimeStamp(), stat.getLoadedClasses()));
             }
             classesView.addClassCount(timeData);
         }
@@ -66,14 +66,15 @@
     }
 
     private VmClassStatView classesView;
+    private VmRef ref;
+    private VmClassStatDAO dao;
 
     // TODO: Use application wide ScheduledExecutorService thread pool.
     private Timer timer;
 
-    private VmClassStatDAO dao;
-
     public VmClassStatController(VmRef ref) {
-        dao = ApplicationContext.getInstance().getDAOFactory().getVmClassStatsDAO(ref);
+        this.ref = ref;
+        dao = ApplicationContext.getInstance().getDAOFactory().getVmClassStatsDAO();
         classesView = createView();
     }
 
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmCpuController.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmCpuController.java	Tue Apr 03 10:22:17 2012 -0400
@@ -52,13 +52,15 @@
 
 public class VmCpuController implements AsyncUiFacade {
 
+    private final VmRef ref;
     private final VmCpuStatDAO dao;
     private final VmCpuView view;
 
     private final Timer timer = new Timer();
 
     public VmCpuController(VmRef ref) {
-        dao = ApplicationContext.getInstance().getDAOFactory().getVmCpuStatDAO(ref);
+        this.ref = ref;
+        dao = ApplicationContext.getInstance().getDAOFactory().getVmCpuStatDAO();
         view = createView();
     }
 
@@ -79,7 +81,7 @@
     }
 
     private void doUpdateVmCpuCharts() {
-        List<VmCpuStat> stats = dao.getLatestVmCpuStats();
+        List<VmCpuStat> stats = dao.getLatestVmCpuStats(ref);
         List<DiscreteTimeData<? extends Number>> toDisplay = new ArrayList<>(stats.size());
         for (VmCpuStat stat: stats) {
             DiscreteTimeData<? extends Number> data =
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmGcController.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmGcController.java	Tue Apr 03 10:22:17 2012 -0400
@@ -63,7 +63,7 @@
 
 public class VmGcController implements AsyncUiFacade {
 
-    private final VmRef vmRef;
+    private final VmRef ref;
     private final VmGcView view;
 
     private final VmGcStatDAO gcDao;
@@ -74,12 +74,12 @@
     private final Timer timer = new Timer();
 
     public VmGcController(VmRef ref) {
-        this.vmRef = ref;
+        this.ref = ref;
         this.view = createView();
 
         DAOFactory df = ApplicationContext.getInstance().getDAOFactory();
-        gcDao = df.getVmGcStatDAO(vmRef);
-        memDao = df.getVmMemoryStatDAO(vmRef);
+        gcDao = df.getVmGcStatDAO();
+        memDao = df.getVmMemoryStatDAO();
     }
 
     protected VmGcView createView() {
@@ -114,7 +114,7 @@
 
     private void doUpdateCollectorData() {
         Map<String, List<DiscreteTimeData<? extends Number>>> dataToAdd = new HashMap<>();
-        for (VmGcStat stat : gcDao.getLatestVmGcStats()) {
+        for (VmGcStat stat : gcDao.getLatestVmGcStats(ref)) {
             double walltime = 1.0E-6 * stat.getWallTime();
             String collector = stat.getCollectorName();
             List<DiscreteTimeData<? extends Number>> data = dataToAdd.get(collector);
@@ -135,7 +135,7 @@
     }
 
     public String getCollectorGeneration(String collectorName) {
-        VmMemoryStat info = memDao.getLatestMemoryStat();
+        VmMemoryStat info = memDao.getLatestMemoryStat(ref);
 
         for (Generation g: info.getGenerations()) {
             if (g.collector.equals(collectorName)) {
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmMemoryController.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmMemoryController.java	Tue Apr 03 10:22:17 2012 -0400
@@ -52,15 +52,15 @@
 
 public class VmMemoryController implements AsyncUiFacade {
 
-    private final VmRef vmRef;
+    private final VmRef ref;
     private final VmMemoryView view;
     private final VmMemoryStatDAO dao;
 
     private final Timer timer = new Timer();
 
-    public VmMemoryController(VmRef vmRef) {
-        this.vmRef = vmRef;
-        dao = ApplicationContext.getInstance().getDAOFactory().getVmMemoryStatDAO(this.vmRef);
+    public VmMemoryController(VmRef ref) {
+        this.ref = ref;
+        dao = ApplicationContext.getInstance().getDAOFactory().getVmMemoryStatDAO();
         view = createView();
     }
 
@@ -69,7 +69,7 @@
         timer.scheduleAtFixedRate(new TimerTask() {
             @Override
             public void run() {
-                VmMemoryStat info = dao.getLatestMemoryStat();
+                VmMemoryStat info = dao.getLatestMemoryStat(ref);
                 List<Generation> generations = info.getGenerations();
                 for (Generation generation: generations) {
                     List<Space> spaces = generation.spaces;
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmOverviewController.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmOverviewController.java	Tue Apr 03 10:22:17 2012 -0400
@@ -54,7 +54,7 @@
 
 public class VmOverviewController implements AsyncUiFacade {
 
-    private final VmRef vmRef;
+    private final VmRef ref;
     private final VmInfoDAO dao;
     private final DateFormat vmRunningTimeFormat;
 
@@ -63,10 +63,10 @@
     private final VmOverviewView view;
 
     public VmOverviewController(VmRef vmRef) {
-        this.vmRef = vmRef;
+        this.ref = vmRef;
         this.view = createView();
 
-        dao = ApplicationContext.getInstance().getDAOFactory().getVmInfoDAO(this.vmRef);
+        dao = ApplicationContext.getInstance().getDAOFactory().getVmInfoDAO();
 
         vmRunningTimeFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.FULL);
         timer = new Timer();
@@ -78,7 +78,7 @@
 
             @Override
             public void run() {
-                VmInfo info = dao.getVmInfo();
+                VmInfo info = dao.getVmInfo(ref);
                 view.setVmPid(((Integer) info.getVmPid()).toString());
                 long actualStartTime = info.getStartTimeStamp();
                 view.setVmStartTimeStamp(vmRunningTimeFormat.format(new Date(actualStartTime)));
--- a/client/src/test/java/com/redhat/thermostat/client/VmClassStatControllerTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/test/java/com/redhat/thermostat/client/VmClassStatControllerTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -66,10 +66,10 @@
         stats.add(stat1);
 
         VmClassStatDAO vmClassStatDAO = mock(VmClassStatDAO.class);
-        when(vmClassStatDAO.getLatestClassStats()).thenReturn(stats).thenReturn(new ArrayList<VmClassStat>());
+        when(vmClassStatDAO.getLatestClassStats(any(VmRef.class))).thenReturn(stats).thenReturn(new ArrayList<VmClassStat>());
 
         DAOFactory daoFactory = mock(MongoDAOFactory.class);
-        when(daoFactory.getVmClassStatsDAO(any(VmRef.class))).thenReturn(vmClassStatDAO);
+        when(daoFactory.getVmClassStatsDAO()).thenReturn(vmClassStatDAO);
 
         ApplicationContext.getInstance().setDAOFactory(daoFactory);
         VmRef ref = mock(VmRef.class);
--- a/client/src/test/java/com/redhat/thermostat/client/appctx/ApplicationContextUtil.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/test/java/com/redhat/thermostat/client/appctx/ApplicationContextUtil.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,6 +36,8 @@
 
 package com.redhat.thermostat.client.appctx;
 
+import com.redhat.thermostat.client.appctx.ApplicationContext;
+
 public class ApplicationContextUtil {
 
     /**
--- a/client/src/test/java/com/redhat/thermostat/client/ui/HostCpuControllerTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/test/java/com/redhat/thermostat/client/ui/HostCpuControllerTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -93,16 +93,16 @@
         // Setup DAOs.
         HostInfo hostInfo = new HostInfo("fluffhost1", "fluffOs1", "fluffKernel1", "fluffCpu1", 12345, 98765);
         HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
-        when(hostInfoDAO.getHostInfo()).thenReturn(hostInfo);
+        when(hostInfoDAO.getHostInfo(any(HostRef.class))).thenReturn(hostInfo);
 
         CpuStat cpuStat1 = new CpuStat(1l, 10.0, 20.0, 30.0);
         CpuStat cpuStat2 = new CpuStat(2l, 15.0, 25.0, 35.0);
         CpuStatDAO cpuStatDAO = mock(CpuStatDAO.class);
-        when(cpuStatDAO.getLatestCpuStats()).thenReturn(Arrays.asList(cpuStat1, cpuStat2));
+        when(cpuStatDAO.getLatestCpuStats(any(HostRef.class))).thenReturn(Arrays.asList(cpuStat1, cpuStat2));
 
         DAOFactory daoFactory = mock(DAOFactory.class);
-        when(daoFactory.getHostInfoDAO(any(HostRef.class))).thenReturn(hostInfoDAO);
-        when(daoFactory.getCpuStatDAO(any(HostRef.class))).thenReturn(cpuStatDAO);
+        when(daoFactory.getHostInfoDAO()).thenReturn(hostInfoDAO);
+        when(daoFactory.getCpuStatDAO()).thenReturn(cpuStatDAO);
 
         ApplicationContext.getInstance().setDAOFactory(daoFactory);
 
--- a/client/src/test/java/com/redhat/thermostat/client/ui/HostMemoryControllerTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/test/java/com/redhat/thermostat/client/ui/HostMemoryControllerTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -62,17 +62,17 @@
     public void testUpdate() {
         HostInfo hostInfo = new HostInfo("someHost", "someOS", "linux_0.0.1", "lreally_fast_cpu", 2, 1024);
         HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
-        when(hostInfoDAO.getHostInfo()).thenReturn(hostInfo);
+        when(hostInfoDAO.getHostInfo(any(HostRef.class))).thenReturn(hostInfo);
 
         MemoryStat memoryStat = new MemoryStat(1, 2, 3, 4, 5, 6, 7, 8);
         List<MemoryStat> memoryStats = new LinkedList<>();
         memoryStats.add(memoryStat);
         MemoryStatDAO memoryStatDAO = mock(MemoryStatDAO.class);
-        when(memoryStatDAO.getLatestMemoryStats()).thenReturn(memoryStats);
+        when(memoryStatDAO.getLatestMemoryStats(any(HostRef.class))).thenReturn(memoryStats);
 
         DAOFactory daoFactory = mock(MongoDAOFactory.class);
-        when(daoFactory.getHostInfoDAO(any(HostRef.class))).thenReturn(hostInfoDAO);
-        when(daoFactory.getMemoryStatDAO(any(HostRef.class))).thenReturn(memoryStatDAO);
+        when(daoFactory.getHostInfoDAO()).thenReturn(hostInfoDAO);
+        when(daoFactory.getMemoryStatDAO()).thenReturn(memoryStatDAO);
         ApplicationContext.getInstance().setDAOFactory(daoFactory);
 
         HostRef ref = mock(HostRef.class);
--- a/client/src/test/java/com/redhat/thermostat/client/ui/VmCpuControllerTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/client/src/test/java/com/redhat/thermostat/client/ui/VmCpuControllerTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -50,7 +50,7 @@
 import com.redhat.thermostat.client.appctx.ApplicationContext;
 import com.redhat.thermostat.common.dao.DAOFactory;
 import com.redhat.thermostat.common.dao.MongoDAOFactory;
-import com.redhat.thermostat.common.dao.VmCpuStatDAOImpl;
+import com.redhat.thermostat.common.dao.VmCpuStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.model.VmCpuStat;
 
@@ -64,11 +64,11 @@
         List<VmCpuStat> stats = new ArrayList<VmCpuStat>();
         stats.add(stat1);
 
-        VmCpuStatDAOImpl vmCpuStatDAO = mock(VmCpuStatDAOImpl.class);
-        when(vmCpuStatDAO.getLatestVmCpuStats()).thenReturn(stats).thenReturn(new ArrayList<VmCpuStat>());
+        VmCpuStatDAO vmCpuStatDAO = mock(VmCpuStatDAO.class);
+        when(vmCpuStatDAO.getLatestVmCpuStats(any(VmRef.class))).thenReturn(stats).thenReturn(new ArrayList<VmCpuStat>());
 
         DAOFactory daoFactory = mock(MongoDAOFactory.class);
-        when(daoFactory.getVmCpuStatDAO(any(VmRef.class))).thenReturn(vmCpuStatDAO);
+        when(daoFactory.getVmCpuStatDAO()).thenReturn(vmCpuStatDAO);
 
         ApplicationContext.getInstance().setDAOFactory(daoFactory);
         VmRef ref = mock(VmRef.class);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/Converter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -0,0 +1,11 @@
+package com.redhat.thermostat.common.dao;
+
+import com.redhat.thermostat.common.model.Pojo;
+import com.redhat.thermostat.common.storage.Chunk;
+
+interface Converter<T extends Pojo> {
+
+    Chunk toChunk(T pojo);
+
+    T fromChunk(Chunk chunk);
+}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatConverter.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatConverter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -40,9 +40,10 @@
 import com.redhat.thermostat.common.storage.Chunk;
 import com.redhat.thermostat.common.storage.Key;
 
-public class CpuStatConverter {
+public class CpuStatConverter implements Converter<CpuStat> {
 
-    public Chunk cpuStatToChunk(CpuStat cpuStat) {
+    @Override
+    public Chunk toChunk(CpuStat cpuStat) {
         Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
         chunk.put(Key.TIMESTAMP, cpuStat.getTimeStamp());
         chunk.put(CpuStatDAO.cpu5LoadKey, cpuStat.getLoad5());
@@ -51,7 +52,8 @@
         return chunk;
     }
 
-    public CpuStat chunkToCpuStat(Chunk chunk) {
+    @Override
+    public CpuStat fromChunk(Chunk chunk) {
         long timestamp = chunk.get(Key.TIMESTAMP);
         double load5 = chunk.get(CpuStatDAO.cpu5LoadKey);
         double load10 = chunk.get(CpuStatDAO.cpu10LoadKey);
--- a/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java	Tue Apr 03 10:22:17 2012 -0400
@@ -48,8 +48,8 @@
     static Key<Double> cpu10LoadKey = new Key<>("10load", false);
     static Key<Double> cpu15LoadKey = new Key<>("15load", false);
 
-    public static final Category cpuStatCategory = new Category("cpu-stats",
+    static final Category cpuStatCategory = new Category("cpu-stats",
             Key.TIMESTAMP, cpu5LoadKey, cpu10LoadKey, cpu15LoadKey);
 
-    public List<CpuStat> getLatestCpuStats();
+    List<CpuStat> getLatestCpuStats(HostRef ref);
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,46 +36,33 @@
 
 package com.redhat.thermostat.common.dao;
 
-import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import com.redhat.thermostat.common.model.CpuStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
 import com.redhat.thermostat.common.storage.Storage;
 
 class CpuStatDAOImpl implements CpuStatDAO {
 
     private Storage storage;
-    private HostRef hostRef;
 
-    private long lastUpdate = Long.MIN_VALUE;
+    private Converter<CpuStat> converter = new CpuStatConverter();;
 
-    public CpuStatDAOImpl(Storage storage, HostRef hostRef) {
+    private Map<HostRef, HostLatestPojoListGetter<CpuStat>> getters = new HashMap<>();
+
+    CpuStatDAOImpl(Storage storage) {
         this.storage = storage;
-        this.hostRef = hostRef;
     }
 
     @Override
-    public List<CpuStat> getLatestCpuStats() {
-        ArrayList<CpuStat> result = new ArrayList<>();
-        Chunk query = new Chunk(CpuStatDAO.cpuStatCategory, false);
-        query.put(Key.AGENT_ID, hostRef.getAgentId());
-        if (lastUpdate != Long.MIN_VALUE) {
-            // TODO once we have an index and the 'column' is of type long, use
-            // a query which can utilize an index. this one doesn't
-            query.put(Key.WHERE, "this.timestamp > " + lastUpdate);
+    public List<CpuStat> getLatestCpuStats(HostRef ref) {
+        HostLatestPojoListGetter<CpuStat> getter = getters.get(ref);
+        if (getter == null) {
+            getter = new HostLatestPojoListGetter<CpuStat>(storage, CpuStatDAO.cpuStatCategory, converter, ref);
+            getters.put(ref, getter);
         }
-        Cursor cursor = storage.findAll(query);
-        CpuStatConverter converter = new CpuStatConverter();
-        while (cursor.hasNext()) {
-            Chunk chunk = cursor.next();
-            CpuStat stat = converter.chunkToCpuStat(chunk);
-            result.add(stat);
-            lastUpdate = Math.max(stat.getTimeStamp(), lastUpdate);
-        }
-        return result;
+        return getter.getLatest();
     }
 
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,34 +36,30 @@
 
 package com.redhat.thermostat.common.dao;
 
-import com.redhat.thermostat.common.storage.Storage;
 
 public interface DAOFactory {
-
-    public Storage getStorage();
-
     /**
      * TODO: This will be replaced by getStorage() as soon as Storage and Connection have been merged.
      */
     public Connection getConnection();
 
-    public VmCpuStatDAO getVmCpuStatDAO(VmRef ref);
+    public HostInfoDAO getHostInfoDAO();
 
-    public VmClassStatDAO getVmClassStatsDAO(VmRef ref);
+    public CpuStatDAO getCpuStatDAO();
 
-    public VmGcStatDAO getVmGcStatDAO(VmRef ref);
+    public MemoryStatDAO getMemoryStatDAO();
 
-    public VmInfoDAO getVmInfoDAO(VmRef ref);
+    public NetworkInterfaceInfoDAO getNetworkInterfaceInfoDAO();
 
-    public VmMemoryStatDAO getVmMemoryStatDAO(VmRef ref);
+    public VmInfoDAO getVmInfoDAO();
 
-    public HostInfoDAO getHostInfoDAO(HostRef ref);
+    public VmCpuStatDAO getVmCpuStatDAO();
 
-    public CpuStatDAO getCpuStatDAO(HostRef ref);
+    public VmMemoryStatDAO getVmMemoryStatDAO();
 
-    public MemoryStatDAO getMemoryStatDAO(HostRef ref);
+    public VmClassStatDAO getVmClassStatsDAO();
 
-    public NetworkInterfaceInfoDAO getNetworkInterfaceInfoDAO(HostRef ref);
+    public VmGcStatDAO getVmGcStatDAO();
 
     public HostRefDAO getHostRefDAO();
 
--- a/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoConverter.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoConverter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -39,9 +39,10 @@
 import com.redhat.thermostat.common.model.HostInfo;
 import com.redhat.thermostat.common.storage.Chunk;
 
-public class HostInfoConverter {
+public class HostInfoConverter implements Converter<HostInfo> {
 
-    public Chunk hostInfoToChunk(HostInfo hostInfo) {
+    @Override
+    public Chunk toChunk(HostInfo hostInfo) {
         Chunk chunk = new Chunk(HostInfoDAO.hostInfoCategory, false);
         chunk.put(HostInfoDAO.hostNameKey, hostInfo.getHostname());
         chunk.put(HostInfoDAO.osNameKey, hostInfo.getOsName());
@@ -52,7 +53,8 @@
         return chunk;
     }
 
-    public HostInfo chunkToHostInfo(Chunk chunk) {
+    @Override
+    public HostInfo fromChunk(Chunk chunk) {
         String hostName = chunk.get(HostInfoDAO.hostNameKey);
         String osName = chunk.get(HostInfoDAO.osNameKey);
         String osKernel = chunk.get(HostInfoDAO.osKernelKey);
--- a/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java	Tue Apr 03 10:22:17 2012 -0400
@@ -49,9 +49,9 @@
     static Key<String> cpuModelKey = new Key<>("cpu_model", false);
     static Key<Long> hostMemoryTotalKey = new Key<>("memory_total", false);
 
-    public static final Category hostInfoCategory = new Category("host-info",
+    static final Category hostInfoCategory = new Category("host-info",
             hostNameKey, osNameKey, osKernelKey,
             cpuCountKey, cpuModelKey, hostMemoryTotalKey);
 
-    public HostInfo getHostInfo();
+    HostInfo getHostInfo(HostRef ref);
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAOImpl.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAOImpl.java	Tue Apr 03 10:22:17 2012 -0400
@@ -42,21 +42,19 @@
 import com.redhat.thermostat.common.storage.Storage;
 
 class HostInfoDAOImpl implements HostInfoDAO {
-    private HostRef ref;
     private Storage storage;
     private HostInfoConverter converter;
 
-    public HostInfoDAOImpl(Storage storage, HostRef hostRef) {
-        ref = hostRef;
+    public HostInfoDAOImpl(Storage storage) {
         this.storage = storage;
         converter = new HostInfoConverter();
     }
 
     @Override
-    public HostInfo getHostInfo() {
+    public HostInfo getHostInfo(HostRef ref) {
         Chunk query = new Chunk(HostInfoDAO.hostInfoCategory, false);
         query.put(Key.AGENT_ID, ref.getAgentId());
         Chunk result = storage.find(query);
-        return result == null ? null : converter.chunkToHostInfo(result);
+        return result == null ? null : converter.fromChunk(result);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -0,0 +1,65 @@
+package com.redhat.thermostat.common.dao;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.common.model.TimeStampedPojo;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+class HostLatestPojoListGetter<T extends TimeStampedPojo> implements LatestPojoListGetter<T> {
+
+    private Storage storage;
+    private Category cat;
+    private Converter<T> converter;
+    private HostRef ref;
+
+    private Map<HostRef, Long> lastUpdateTimes = new HashMap<>();
+
+    HostLatestPojoListGetter(Storage storage, Category cat, Converter<T> converter, HostRef ref) {
+        this.storage = storage;
+        this.cat = cat;
+        this.converter = converter;
+        this.ref = ref;
+    }
+
+    @Override
+    public List<T> getLatest() {
+        Chunk query = buildQuery();
+        return getLatest(query);
+    }
+
+    private List<T> getLatest(Chunk query) {
+        // TODO if multiple threads will be using this utility class, there may be some issues
+        // with the updateTimes
+        Long lastUpdate = lastUpdateTimes.get(ref);
+        Cursor cursor = storage.findAll(query);
+        List<T> result = new ArrayList<>();
+        while (cursor.hasNext()) {
+            Chunk chunk = cursor.next();
+            T pojo = converter.fromChunk(chunk);
+            result.add(pojo);
+            lastUpdateTimes.put(ref, Math.max(pojo.getTimeStamp(), lastUpdate));
+        }
+        return result;
+    }
+
+    protected Chunk buildQuery() {
+        Chunk query = new Chunk(cat, false);
+        query.put(Key.AGENT_ID, ref.getAgentId());
+        Long lastUpdate = lastUpdateTimes.get(ref);
+        if (lastUpdate != null) {
+            // TODO once we have an index and the 'column' is of type long, use
+            // a query which can utilize an index. this one doesn't
+            query.put(Key.WHERE, "this.timestamp > " + lastUpdate);
+        } else {
+            lastUpdateTimes.put(ref, Long.MIN_VALUE);
+        }
+        return query;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/LatestPojoListGetter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -0,0 +1,9 @@
+package com.redhat.thermostat.common.dao;
+
+import java.util.List;
+
+import com.redhat.thermostat.common.model.Pojo;
+
+interface LatestPojoListGetter<T extends Pojo> {
+    List<T> getLatest();
+}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatConverter.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatConverter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -40,9 +40,10 @@
 import com.redhat.thermostat.common.storage.Chunk;
 import com.redhat.thermostat.common.storage.Key;
 
-public class MemoryStatConverter {
+public class MemoryStatConverter implements Converter<MemoryStat> {
 
-    public Chunk memoryStatToChunk(MemoryStat mem) {
+    @Override
+    public Chunk toChunk(MemoryStat mem) {
         Chunk chunk = new Chunk(MemoryStatDAO.memoryStatCategory, false);
         chunk.put(Key.TIMESTAMP, mem.getTimeStamp());
         chunk.put(MemoryStatDAO.memoryTotalKey, mem.getTotal());
@@ -55,7 +56,8 @@
         return chunk;
     }
 
-    public MemoryStat chunkToMemoryStat(Chunk chunk) {
+    @Override
+    public MemoryStat fromChunk(Chunk chunk) {
         long timestamp = chunk.get(Key.TIMESTAMP);
         long total = chunk.get(MemoryStatDAO.memoryTotalKey);
         long free = chunk.get(MemoryStatDAO.memoryFreeKey);
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAO.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAO.java	Tue Apr 03 10:22:17 2012 -0400
@@ -52,9 +52,9 @@
     static Key<Long> memorySwapFreeKey = new Key<>("swap-free", false);
     static Key<Long> memoryCommitLimitKey = new Key<>("commit-limit", false);
 
-    public static final Category memoryStatCategory = new Category("memory-stats",
+    static final Category memoryStatCategory = new Category("memory-stats",
             Key.TIMESTAMP, memoryTotalKey, memoryFreeKey, memoryBuffersKey,
             memoryCachedKey, memorySwapTotalKey, memorySwapFreeKey, memoryCommitLimitKey);
 
-    public List<MemoryStat> getLatestMemoryStats();
+    public List<MemoryStat> getLatestMemoryStats(HostRef ref);
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAOImpl.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/MemoryStatDAOImpl.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,45 +36,32 @@
 
 package com.redhat.thermostat.common.dao;
 
-import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import com.redhat.thermostat.common.model.MemoryStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
 import com.redhat.thermostat.common.storage.Storage;
 
 class MemoryStatDAOImpl implements MemoryStatDAO {
 
     private Storage storage;
-    private HostRef hostRef;
 
-    private long lastUpdate = Long.MIN_VALUE;
+    private Converter<MemoryStat> converter = new MemoryStatConverter();
 
-    public MemoryStatDAOImpl(Storage storage, HostRef hostRef) {
+    private Map<HostRef, HostLatestPojoListGetter<MemoryStat>> getters = new HashMap<>();
+
+    MemoryStatDAOImpl(Storage storage) {
         this.storage = storage;
-        this.hostRef = hostRef;
     }
 
     @Override
-    public List<MemoryStat> getLatestMemoryStats() {
-        Chunk query = new Chunk(MemoryStatDAO.memoryStatCategory, false);
-        query.put(Key.AGENT_ID, hostRef.getAgentId());
-        if (lastUpdate != Long.MIN_VALUE) {
-            // TODO once we have an index and the 'column' is of type long, use
-            // a query which can utilize an index. this one doesn't
-            query.put(Key.WHERE, "this.timestamp > " + lastUpdate);
+    public List<MemoryStat> getLatestMemoryStats(HostRef ref) {
+        HostLatestPojoListGetter<MemoryStat> getter = getters.get(ref);
+        if (getter == null) {
+            getter = new HostLatestPojoListGetter<MemoryStat>(storage, MemoryStatDAO.memoryStatCategory, converter, ref);
+            getters.put(ref, getter);
         }
-        Cursor cursor = storage.findAll(query);
-        MemoryStatConverter converter = new MemoryStatConverter();
-        List<MemoryStat> result = new ArrayList<>();
-        while (cursor.hasNext()) {
-            Chunk chunk = cursor.next();
-            MemoryStat stat = converter.chunkToMemoryStat(chunk);
-            result.add(stat);
-            lastUpdate = Math.max(stat.getTimeStamp(), lastUpdate);
-        }
-        return result;
+        return getter.getLatest();
     }
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java	Tue Apr 03 10:22:17 2012 -0400
@@ -43,13 +43,14 @@
 
 public class MongoDAOFactory implements DAOFactory {
 
-    private Storage storage;
-    private Connection connection;
+    private final Connection connection;
+    private final Storage storage;
 
     public MongoDAOFactory(ConnectionProvider connProv) {
 
         connection = connProv.createConnection();
         final MongoStorage mongoStorage = new MongoStorage(connection);
+        storage = mongoStorage;
         connection.addListener(new ConnectionListener() {
 
             @Override
@@ -59,22 +60,6 @@
                 }
             }
         });
-        storage = mongoStorage;
-    }
-
-    @Override
-    public Storage getStorage() {
-        return storage;
-    }
-
-    @Override
-    public VmCpuStatDAO getVmCpuStatDAO(VmRef ref) {
-        return new VmCpuStatDAOImpl(storage, ref);
-    }
-
-    @Override
-    public VmClassStatDAO getVmClassStatsDAO(VmRef ref) {
-        return new VmClassStatDAOImpl(storage, ref);
     }
 
     @Override
@@ -83,37 +68,47 @@
     }
 
     @Override
-    public HostInfoDAO getHostInfoDAO(HostRef ref) {
-        return new HostInfoDAOImpl(storage, ref);
+    public HostInfoDAO getHostInfoDAO() {
+        return new HostInfoDAOImpl(storage);
     }
 
     @Override
-    public CpuStatDAO getCpuStatDAO(HostRef ref) {
-        return new CpuStatDAOImpl(storage, ref);
+    public CpuStatDAO getCpuStatDAO() {
+        return new CpuStatDAOImpl(storage);
     }
 
     @Override
-    public MemoryStatDAO getMemoryStatDAO(HostRef ref) {
-        return new MemoryStatDAOImpl(storage, ref);
+    public MemoryStatDAO getMemoryStatDAO() {
+        return new MemoryStatDAOImpl(storage);
+    }
+
+    @Override
+    public NetworkInterfaceInfoDAO getNetworkInterfaceInfoDAO() {
+        return new NetworkInterfaceInfoDAOImpl(storage);
     }
 
     @Override
-    public NetworkInterfaceInfoDAO getNetworkInterfaceInfoDAO(HostRef ref) {
-        return new NetworkInterfaceInfoDAOImpl(storage, ref);
+    public VmInfoDAO getVmInfoDAO() {
+        return new VmInfoDAOImpl(storage);
     }
 
     @Override
-    public VmGcStatDAO getVmGcStatDAO(VmRef ref) {
-        return new VmGcStatDAOImpl(storage, ref);
+    public VmCpuStatDAO getVmCpuStatDAO() {
+        return new VmCpuStatDAOImpl(storage);
+    }
+
+    public VmMemoryStatDAO getVmMemoryStatDAO() {
+        return new VmMemoryStatDAOImpl(storage);
     }
 
     @Override
-    public VmInfoDAO getVmInfoDAO(VmRef ref) {
-        return new VmInfoDAOImpl(storage, ref);
+    public VmClassStatDAO getVmClassStatsDAO() {
+        return new VmClassStatDAOImpl(storage);
     }
 
-    public VmMemoryStatDAO getVmMemoryStatDAO(VmRef ref) {
-        return new VmMemoryStatDAOImpl(storage, ref);
+    @Override
+    public VmGcStatDAO getVmGcStatDAO() {
+        return new VmGcStatDAOImpl(storage);
     }
 
     @Override
--- a/common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverter.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -39,9 +39,10 @@
 import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
 import com.redhat.thermostat.common.storage.Chunk;
 
-public class NetworkInterfaceInfoConverter {
+public class NetworkInterfaceInfoConverter implements Converter<NetworkInterfaceInfo> {
 
-    public Chunk networkInfoToChunk(NetworkInterfaceInfo info) {
+    @Override
+    public Chunk toChunk(NetworkInterfaceInfo info) {
         Chunk chunk = new Chunk(NetworkInterfaceInfoDAO.networkInfoCategory, true);
         chunk.put(NetworkInterfaceInfoDAO.ifaceKey, info.getInterfaceName());
         String ip4 = info.getIp4Addr();
@@ -55,7 +56,8 @@
         return chunk;
     }
 
-    public NetworkInterfaceInfo chunkToNetworkInfo(Chunk chunk) {
+    @Override
+    public NetworkInterfaceInfo fromChunk(Chunk chunk) {
         NetworkInterfaceInfo info = new NetworkInterfaceInfo(chunk.get(NetworkInterfaceInfoDAO.ifaceKey));
         info.setIp4Addr(chunk.get(NetworkInterfaceInfoDAO.ip4AddrKey));
         info.setIp6Addr(chunk.get(NetworkInterfaceInfoDAO.ip6AddrKey));
--- a/common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAO.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAO.java	Tue Apr 03 10:22:17 2012 -0400
@@ -48,8 +48,8 @@
     static Key<String> ip4AddrKey = new Key<>("ipv4addr", false);
     static Key<String> ip6AddrKey = new Key<>("ipv6addr", false);
 
-    public static final Category networkInfoCategory = new Category("network-info",
+    static final Category networkInfoCategory = new Category("network-info",
             Key.TIMESTAMP, ifaceKey, ip4AddrKey, ip6AddrKey);
 
-    public List<NetworkInterfaceInfo> getNetworkInterfaces();
+    public List<NetworkInterfaceInfo> getNetworkInterfaces(HostRef ref);
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOImpl.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOImpl.java	Tue Apr 03 10:22:17 2012 -0400
@@ -45,18 +45,16 @@
 import com.redhat.thermostat.common.storage.Key;
 import com.redhat.thermostat.common.storage.Storage;
 
-public class NetworkInterfaceInfoDAOImpl implements NetworkInterfaceInfoDAO {
+class NetworkInterfaceInfoDAOImpl implements NetworkInterfaceInfoDAO {
 
     private Storage storage;
-    private HostRef ref;
 
-    public NetworkInterfaceInfoDAOImpl(Storage storage, HostRef ref) {
+    NetworkInterfaceInfoDAOImpl(Storage storage) {
         this.storage = storage;
-        this.ref = ref;
     }
 
     @Override
-    public List<NetworkInterfaceInfo> getNetworkInterfaces() {
+    public List<NetworkInterfaceInfo> getNetworkInterfaces(HostRef ref) {
         Chunk query = new Chunk(NetworkInterfaceInfoDAO.networkInfoCategory, false);
         query.put(Key.AGENT_ID, ref.getAgentId());
 
@@ -65,7 +63,7 @@
         List<NetworkInterfaceInfo> result = new ArrayList<>();
         while (cursor.hasNext()) {
             Chunk chunk = cursor.next();
-            NetworkInterfaceInfo stat = converter.chunkToNetworkInfo(chunk);
+            NetworkInterfaceInfo stat = converter.fromChunk(chunk);
             result.add(stat);
         }
         return result;
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatConverter.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatConverter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -40,20 +40,22 @@
 import com.redhat.thermostat.common.storage.Chunk;
 import com.redhat.thermostat.common.storage.Key;
 
-public class VmClassStatConverter {
+public class VmClassStatConverter implements Converter<VmClassStat> {
 
-    public Chunk vmClassStatToChunk(VmClassStat vmClassStat) {
+    @Override
+    public Chunk toChunk(VmClassStat vmClassStat) {
         Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
-        chunk.put(VmClassStatDAO.vmIdKey, vmClassStat.getVmId());
-        chunk.put(Key.TIMESTAMP, vmClassStat.getTimestamp());
+        chunk.put(Key.VM_ID, vmClassStat.getVmId());
+        chunk.put(Key.TIMESTAMP, vmClassStat.getTimeStamp());
         chunk.put(VmClassStatDAO.loadedClassesKey, vmClassStat.getLoadedClasses());
         return chunk;
     }
 
-    public VmClassStat chunkToVmClassStat(Chunk chunk) {
+    @Override
+    public VmClassStat fromChunk(Chunk chunk) {
         long timestamp = chunk.get(Key.TIMESTAMP);
         long loadedClasses = chunk.get(VmClassStatDAO.loadedClassesKey);
-        int vmId = chunk.get(VmClassStatDAO.vmIdKey);
+        int vmId = chunk.get(Key.VM_ID);
         return new VmClassStat(vmId, timestamp, loadedClasses);
     }
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java	Tue Apr 03 10:22:17 2012 -0400
@@ -44,12 +44,11 @@
 
 public interface VmClassStatDAO {
 
-    static final Key<Integer> vmIdKey = new Key<>("vm-id", false);
     static final Key<Long> loadedClassesKey = new Key<>("loadedClasses", false);
 
-    public static final Category vmClassStatsCategory = new Category(
-            "vm-class-stats", vmIdKey, Key.TIMESTAMP, loadedClassesKey);
+    static final Category vmClassStatsCategory = new Category(
+            "vm-class-stats", Key.VM_ID, Key.TIMESTAMP, loadedClassesKey);
 
-    public List<VmClassStat> getLatestClassStats();
+    public List<VmClassStat> getLatestClassStats(VmRef ref);
 
 }
\ No newline at end of file
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,47 +36,32 @@
 
 package com.redhat.thermostat.common.dao;
 
-import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import com.redhat.thermostat.common.model.VmClassStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
 import com.redhat.thermostat.common.storage.Storage;
 
 class VmClassStatDAOImpl implements VmClassStatDAO {
 
-    private VmRef ref;
     private Storage storage;
 
-    private long lastUpdate = Long.MIN_VALUE;
+    private Converter<VmClassStat> converter = new VmClassStatConverter();
 
-    public VmClassStatDAOImpl(Storage storage, VmRef vmRef) {
-        ref = vmRef;
+    private Map<VmRef, VmLatestPojoListGetter<VmClassStat>> getters = new HashMap<>();
+
+    VmClassStatDAOImpl(Storage storage) {
         this.storage = storage;
     }
 
     @Override
-    public List<VmClassStat> getLatestClassStats() {
-        ArrayList<VmClassStat> result = new ArrayList<>();
-        Chunk query = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
-        query.put(Key.AGENT_ID, ref.getAgent().getAgentId());
-        query.put(VmClassStatDAO.vmIdKey, ref.getId());
-        if (lastUpdate != Long.MIN_VALUE) {
-            // TODO once we have an index and the 'column' is of type long, use
-            // a query which can utilize an index. this one doesn't
-            query.put(Key.WHERE, "this.timestamp > " + lastUpdate);
+    public List<VmClassStat> getLatestClassStats(VmRef ref) {
+        VmLatestPojoListGetter<VmClassStat> getter = getters.get(ref);
+        if (getter == null) {
+            getter = new VmLatestPojoListGetter<VmClassStat>(storage, VmClassStatDAO.vmClassStatsCategory, converter, ref);
+            getters.put(ref, getter);
         }
-        Cursor cursor = storage.findAll(query);
-        VmClassStatConverter converter = new VmClassStatConverter();
-        while (cursor.hasNext()) {
-            Chunk current = cursor.next();
-            VmClassStat stat = converter.chunkToVmClassStat(current);
-            result.add(stat);
-            lastUpdate = Math.max(stat.getTimestamp(), lastUpdate);
-        }
-
-        return result;
+        return getter.getLatest();
     }
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatConverter.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatConverter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -40,19 +40,21 @@
 import com.redhat.thermostat.common.storage.Chunk;
 import com.redhat.thermostat.common.storage.Key;
 
-public class VmCpuStatConverter {
+public class VmCpuStatConverter implements Converter<VmCpuStat> {
 
-    public Chunk vmCpuStatToChunk(VmCpuStat vmCpuStat) {
+    @Override
+    public Chunk toChunk(VmCpuStat vmCpuStat) {
         Chunk chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
         chunk.put(Key.TIMESTAMP, vmCpuStat.getTimeStamp());
-        chunk.put(VmCpuStatDAO.vmIdKey, vmCpuStat.getVmId());
+        chunk.put(Key.VM_ID, vmCpuStat.getVmId());
         chunk.put(VmCpuStatDAO.vmCpuLoadKey, vmCpuStat.getCpuLoad());
         return chunk;
     }
 
-    public VmCpuStat chunkToVmCpuStat(Chunk chunk) {
+    @Override
+    public VmCpuStat fromChunk(Chunk chunk) {
         long timestamp = chunk.get(Key.TIMESTAMP);
-        int vmId = chunk.get(VmCpuStatDAO.vmIdKey);
+        int vmId = chunk.get(Key.VM_ID);
         double processorUsage = chunk.get(VmCpuStatDAO.vmCpuLoadKey);
         return new VmCpuStat(timestamp, vmId, processorUsage);
     }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAO.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAO.java	Tue Apr 03 10:22:17 2012 -0400
@@ -42,14 +42,13 @@
 import com.redhat.thermostat.common.storage.Category;
 import com.redhat.thermostat.common.storage.Key;
 
-public abstract class VmCpuStatDAO {
+public interface VmCpuStatDAO {
 
-    static final Key<Integer> vmIdKey = new Key<>("vm-id", false);
     static final Key<Double> vmCpuLoadKey = new Key<>("processor-usage", false);
 
-    public static final Category vmCpuStatCategory = new Category("vm-cpu-stats",
-            Key.TIMESTAMP, vmCpuLoadKey, vmIdKey);
+    static final Category vmCpuStatCategory = new Category("vm-cpu-stats",
+            Key.VM_ID, Key.TIMESTAMP, vmCpuLoadKey);
 
-    public abstract List<VmCpuStat> getLatestVmCpuStats();
+    public abstract List<VmCpuStat> getLatestVmCpuStats(VmRef ref);
 
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAOImpl.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAOImpl.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,47 +36,32 @@
 
 package com.redhat.thermostat.common.dao;
 
-import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import com.redhat.thermostat.common.model.VmCpuStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
 import com.redhat.thermostat.common.storage.Storage;
 
-public class VmCpuStatDAOImpl extends VmCpuStatDAO {
+class VmCpuStatDAOImpl implements VmCpuStatDAO {
 
     private final Storage storage;
-    private final VmRef vmRef;
 
-    private long lastUpdate = Long.MIN_VALUE;;
+    private Converter<VmCpuStat> converter = new VmCpuStatConverter();
 
-    public VmCpuStatDAOImpl(Storage storage, VmRef vmRef) {
+    private Map<VmRef, VmLatestPojoListGetter<VmCpuStat>> getters = new HashMap<>();
+
+    VmCpuStatDAOImpl(Storage storage) {
         this.storage = storage;
-        this.vmRef = vmRef;
     }
 
     @Override
-    public List<VmCpuStat> getLatestVmCpuStats() {
-        ArrayList<VmCpuStat> result = new ArrayList<>();
-        Chunk query = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
-        query.put(Key.AGENT_ID, vmRef.getAgent().getAgentId());
-        query.put(VmCpuStatDAO.vmIdKey, vmRef.getId());
-        if (lastUpdate != Long.MIN_VALUE) {
-            // TODO once we have an index and the 'column' is of type long, use
-            // a query which can utilize an index. this one doesn't
-            query.put(Key.WHERE, "this.timestamp > " + lastUpdate);
+    public List<VmCpuStat> getLatestVmCpuStats(VmRef ref) {
+        VmLatestPojoListGetter<VmCpuStat> getter = getters.get(ref);
+        if (getter == null) {
+            getter = new VmLatestPojoListGetter<VmCpuStat>(storage, VmGcStatDAO.vmGcStatsCategory, converter, ref);
+            getters.put(ref, getter);
         }
-        Cursor cursor = storage.findAll(query);
-        while (cursor.hasNext()) {
-            Chunk current = cursor.next();
-            VmCpuStat stat = new VmCpuStatConverter().chunkToVmCpuStat(current);
-            result.add(stat);
-            lastUpdate = Math.max(stat.getTimeStamp(), lastUpdate);
-        }
-
-        return result;
-
+        return getter.getLatest();
     }
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatConverter.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatConverter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -40,12 +40,13 @@
 import com.redhat.thermostat.common.storage.Chunk;
 import com.redhat.thermostat.common.storage.Key;
 
-public class VmGcStatConverter {
+public class VmGcStatConverter implements Converter<VmGcStat> {
 
-    public Chunk vmGcStatToChunk(VmGcStat vmGcStat) {
+    @Override
+    public Chunk toChunk(VmGcStat vmGcStat) {
         Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatsCategory, false);
 
-        chunk.put(VmGcStatDAO.vmIdKey, vmGcStat.getVmId());
+        chunk.put(Key.VM_ID, vmGcStat.getVmId());
         chunk.put(Key.TIMESTAMP, vmGcStat.getTimeStamp());
         chunk.put(VmGcStatDAO.collectorKey, vmGcStat.getCollectorName());
         chunk.put(VmGcStatDAO.runCountKey, vmGcStat.getRunCount());
@@ -54,8 +55,9 @@
         return chunk;
     }
 
-    public VmGcStat chunkToVmGcStat(Chunk chunk) {
-        int vmId = chunk.get(VmGcStatDAO.vmIdKey);
+    @Override
+    public VmGcStat fromChunk(Chunk chunk) {
+        int vmId = chunk.get(Key.VM_ID);
         long timestamp = chunk.get(Key.TIMESTAMP);
         String collectorName = chunk.get(VmGcStatDAO.collectorKey);
         long runCount = chunk.get(VmGcStatDAO.runCountKey);
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java	Tue Apr 03 10:22:17 2012 -0400
@@ -44,15 +44,14 @@
 
 public interface VmGcStatDAO {
 
-    static final Key<Integer> vmIdKey = new Key<>("vm-id", false);
     static final Key<String> collectorKey = new Key<>("collector", false);
     static final Key<Long> runCountKey = new Key<>("runtime-count", false);
     /** time in microseconds */
     static final Key<Long> wallTimeKey = new Key<>("wall-time", false);
 
-    public static final Category vmGcStatsCategory = new Category("vm-gc-stats",
-            vmIdKey, Key.TIMESTAMP, collectorKey,
+    static final Category vmGcStatsCategory = new Category("vm-gc-stats",
+            Key.VM_ID, Key.TIMESTAMP, collectorKey,
             runCountKey, wallTimeKey);
 
-    public List<VmGcStat> getLatestVmGcStats();
+    public List<VmGcStat> getLatestVmGcStats(VmRef ref);
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAOImpl.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAOImpl.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,47 +36,33 @@
 
 package com.redhat.thermostat.common.dao;
 
-import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import com.redhat.thermostat.common.model.VmGcStat;
-import com.redhat.thermostat.common.storage.Chunk;
-import com.redhat.thermostat.common.storage.Cursor;
-import com.redhat.thermostat.common.storage.Key;
 import com.redhat.thermostat.common.storage.Storage;
 
-public class VmGcStatDAOImpl implements VmGcStatDAO {
+class VmGcStatDAOImpl implements VmGcStatDAO {
 
     private Storage storage;
-    private VmRef ref;
 
-    private long lastUpdate = Long.MIN_VALUE;
+    private Converter<VmGcStat> converter = new VmGcStatConverter();
 
-    public VmGcStatDAOImpl(Storage storage, VmRef ref) {
+    private Map<VmRef, VmLatestPojoListGetter<VmGcStat>> getters = new HashMap<>();
+
+    VmGcStatDAOImpl(Storage storage) {
         this.storage = storage;
-        this.ref = ref;
     }
 
     @Override
-    public List<VmGcStat> getLatestVmGcStats() {
-        List<VmGcStat> result = new ArrayList<>();
-        Chunk query = new Chunk(VmGcStatDAO.vmGcStatsCategory, false);
-        query.put(Key.AGENT_ID, ref.getAgent().getAgentId());
-        query.put(VmGcStatDAO.vmIdKey, ref.getId());
-        if (lastUpdate != Long.MIN_VALUE) {
-            // TODO once we have an index and the 'column' is of type long, use
-            // a query which can utilize an index. this one doesn't
-            query.put(Key.WHERE, "this.timestamp > " + lastUpdate);
+    public List<VmGcStat> getLatestVmGcStats(VmRef ref) {
+        VmLatestPojoListGetter<VmGcStat> getter = getters.get(ref);
+        if (getter == null) {
+            getter = new VmLatestPojoListGetter<VmGcStat>(storage, VmGcStatDAO.vmGcStatsCategory, converter, ref);
+            getters.put(ref, getter);
         }
-        Cursor cursor = storage.findAll(query);
-        VmGcStatConverter converter = new VmGcStatConverter();
-        while (cursor.hasNext()) {
-            Chunk current = cursor.next();
-            VmGcStat stat = converter.chunkToVmGcStat(current);
-            result.add(stat);
-            lastUpdate = Math.max(stat.getTimeStamp(), lastUpdate);
-        }
-        return result;
+        return getter.getLatest();
     }
 
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoConverter.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoConverter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -42,9 +42,10 @@
 import com.redhat.thermostat.common.model.VmInfo;
 import com.redhat.thermostat.common.storage.Chunk;
 
-public class VmInfoConverter {
+public class VmInfoConverter implements Converter<VmInfo> {
 
-    public Chunk vmInfoToChunk(VmInfo info) {
+    @Override
+    public Chunk toChunk(VmInfo info) {
         Chunk chunk = new Chunk(VmInfoDAO.vmInfoCategory, true);
 
         chunk.put(VmInfoDAO.vmIdKey, info.getVmId());
@@ -65,7 +66,8 @@
         return chunk;
     }
 
-    public VmInfo chunkToVmInfo(Chunk chunk) {
+    @Override
+    public VmInfo fromChunk(Chunk chunk) {
         int vmId = chunk.get(VmInfoDAO.vmIdKey);
         long startTime = chunk.get(VmInfoDAO.startTimeKey);
         long stopTime = chunk.get(VmInfoDAO.stopTimeKey);
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAO.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAO.java	Tue Apr 03 10:22:17 2012 -0400
@@ -45,8 +45,7 @@
 
 public interface VmInfoDAO {
 
-    // FIXME make it non-public
-    public static final Key<Integer> vmIdKey = new Key<>("vm-id", true);
+    static final Key<Integer> vmIdKey = new Key<>("vm-id", true);
     static final Key<Integer> vmPidKey = new Key<>("vm-pid", false);
     static final Key<String> runtimeVersionKey = new Key<>("runtime-version", false);
     static final Key<String> javaHomeKey = new Key<>("java-home", false);
@@ -60,15 +59,14 @@
     static final Key<Map<String, String>> environmentKey = new Key<>("environment", false);
     static final Key<List<String>> librariesKey = new Key<>("libraries", false);
     static final Key<Long> startTimeKey = new Key<>("start-time", false);
-    // FIXME make it non-public
-    public static final Key<Long> stopTimeKey = new Key<>("stop-time", false);
+    static final Key<Long> stopTimeKey = new Key<>("stop-time", false);
 
-    public static final Category vmInfoCategory = new Category("vm-info",
+    static final Category vmInfoCategory = new Category("vm-info",
             vmIdKey, vmPidKey, runtimeVersionKey, javaHomeKey,
             mainClassKey, commandLineKey,
             vmArgumentsKey, vmNameKey, vmInfoKey, vmVersionKey,
             propertiesKey, environmentKey, librariesKey,
             startTimeKey, stopTimeKey);
 
-    public VmInfo getVmInfo();
+    public VmInfo getVmInfo(VmRef ref);
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAOImpl.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmInfoDAOImpl.java	Tue Apr 03 10:22:17 2012 -0400
@@ -41,25 +41,23 @@
 import com.redhat.thermostat.common.storage.Key;
 import com.redhat.thermostat.common.storage.Storage;
 
-public class VmInfoDAOImpl implements VmInfoDAO {
+class VmInfoDAOImpl implements VmInfoDAO {
 
     private Storage storage;
-    private VmRef ref;
     private VmInfoConverter converter;
 
-    public VmInfoDAOImpl(Storage storage, VmRef ref) {
+    VmInfoDAOImpl(Storage storage) {
         this.storage = storage;
-        this.ref = ref;
         this.converter = new VmInfoConverter();
     }
 
     @Override
-    public VmInfo getVmInfo() {
+    public VmInfo getVmInfo(VmRef ref) {
         Chunk query = new Chunk(VmInfoDAO.vmInfoCategory, false);
         query.put(Key.AGENT_ID, ref.getAgent().getAgentId());
         query.put(VmInfoDAO.vmIdKey, ref.getId());
         Chunk result = storage.find(query);
-        return converter.chunkToVmInfo(result);
+        return converter.fromChunk(result);
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -0,0 +1,24 @@
+package com.redhat.thermostat.common.dao;
+
+import com.redhat.thermostat.common.model.TimeStampedPojo;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+class VmLatestPojoListGetter<T extends TimeStampedPojo> extends HostLatestPojoListGetter<T> {
+
+    private VmRef vmRef;
+
+    VmLatestPojoListGetter(Storage storage, Category cat, Converter<T> converter, VmRef ref) {
+        super(storage, cat, converter, ref.getAgent());
+        vmRef = ref;
+    }
+
+    @Override
+    protected Chunk buildQuery() {
+        Chunk query = super.buildQuery();
+        query.put(Key.VM_ID, vmRef.getId());
+        return query;
+    }
+}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatConverter.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatConverter.java	Tue Apr 03 10:22:17 2012 -0400
@@ -39,19 +39,19 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import com.mongodb.DBObject;
 import com.redhat.thermostat.common.model.VmMemoryStat;
 import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
 import com.redhat.thermostat.common.model.VmMemoryStat.Space;
 import com.redhat.thermostat.common.storage.Chunk;
 import com.redhat.thermostat.common.storage.Key;
 
-public class VmMemoryStatConverter {
+public class VmMemoryStatConverter implements Converter<VmMemoryStat> {
 
-    public Chunk vmMemoryStatToChunk(VmMemoryStat vmMemStat) {
+    @Override
+    public Chunk toChunk(VmMemoryStat vmMemStat) {
         Chunk chunk = new Chunk(VmMemoryStatDAO.vmMemoryStatsCategory, false);
 
-        chunk.put(VmMemoryStatDAO.vmIdKey, vmMemStat.getVmId());
+        chunk.put(Key.VM_ID, vmMemStat.getVmId());
         chunk.put(Key.TIMESTAMP, vmMemStat.getTimeStamp());
 
         Generation newGen = vmMemStat.getGeneration("new");
@@ -98,7 +98,8 @@
         return chunk;
     }
 
-    public VmMemoryStat chunkToVmMemoryStat(Chunk chunk) {
+    @Override
+    public VmMemoryStat fromChunk(Chunk chunk) {
         Space space = null;
         List<Space> spaces = null;
 
@@ -176,6 +177,6 @@
 
         gens.add(permGen);
 
-        return new VmMemoryStat(chunk.get(Key.TIMESTAMP), chunk.get(VmMemoryStatDAO.vmIdKey), gens);
+        return new VmMemoryStat(chunk.get(Key.TIMESTAMP), chunk.get(Key.VM_ID), gens);
     }
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java	Tue Apr 03 10:22:17 2012 -0400
@@ -42,8 +42,6 @@
 
 public interface VmMemoryStatDAO {
 
-    static final Key<Integer> vmIdKey = new Key<>("vm-id", false);
-
     static final Key<String> edenGenKey = new Key<>("eden.gen", false);
     static final Key<String> edenCollectorKey = new Key<>("eden.collector", false);
     static final Key<Long> edenCapacityKey = new Key<>("eden.capacity", false);
@@ -74,8 +72,8 @@
     static final Key<Long> permMaxCapacityKey = new Key<>("perm.max-capacity", false);
     static final Key<Long> permUsedKey = new Key<>("perm.used", false);
 
-    public static final Category vmMemoryStatsCategory = new Category("vm-memory-stats",
-            vmIdKey, Key.TIMESTAMP,
+    static final Category vmMemoryStatsCategory = new Category("vm-memory-stats",
+            Key.VM_ID, Key.TIMESTAMP,
             edenGenKey, edenCollectorKey,
             edenCapacityKey, edenMaxCapacityKey,edenUsedKey,
             s0GenKey, s0CollectorKey, s0CapacityKey,
@@ -87,6 +85,6 @@
             permGenKey, permCollectorKey, permCapacityKey,
             permMaxCapacityKey, permUsedKey);
 
-    public VmMemoryStat getLatestMemoryStat();
+    public VmMemoryStat getLatestMemoryStat(VmRef ref);
 
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java	Tue Apr 03 10:22:17 2012 -0400
@@ -42,24 +42,22 @@
 import com.redhat.thermostat.common.storage.Key;
 import com.redhat.thermostat.common.storage.Storage;
 
-public class VmMemoryStatDAOImpl implements VmMemoryStatDAO {
+class VmMemoryStatDAOImpl implements VmMemoryStatDAO {
 
     private final Storage storage;
-    private final VmRef ref;
 
-    public VmMemoryStatDAOImpl(Storage storage, VmRef ref) {
+    VmMemoryStatDAOImpl(Storage storage) {
         this.storage = storage;
-        this.ref = ref;
     }
 
     @Override
-    public VmMemoryStat getLatestMemoryStat() {
+    public VmMemoryStat getLatestMemoryStat(VmRef ref) {
         Chunk query = new Chunk(VmMemoryStatDAO.vmMemoryStatsCategory, false);
         query.put(Key.AGENT_ID, ref.getAgent().getAgentId());
-        query.put(VmMemoryStatDAO.vmIdKey, ref.getId());
+        query.put(Key.VM_ID, ref.getId());
         Cursor cursor = storage.findAll(query).sort(Key.TIMESTAMP, Cursor.SortDirection.DESCENDING).limit(1);
         if (cursor.hasNext()) {
-            return new VmMemoryStatConverter().chunkToVmMemoryStat(cursor.next());
+            return new VmMemoryStatConverter().fromChunk(cursor.next());
         }
         return null;
     }
--- a/common/src/main/java/com/redhat/thermostat/common/model/CpuStat.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/model/CpuStat.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,7 +36,7 @@
 
 package com.redhat.thermostat.common.model;
 
-public class CpuStat {
+public class CpuStat implements TimeStampedPojo {
 
     public static final double INVALID_LOAD = Double.MIN_VALUE;
 
@@ -68,6 +68,7 @@
         return new double[] { load5, load10, load15 };
     }
 
+    @Override
     public long getTimeStamp() {
         return timeStamp;
     }
--- a/common/src/main/java/com/redhat/thermostat/common/model/HostInfo.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/model/HostInfo.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,7 +36,7 @@
 
 package com.redhat.thermostat.common.model;
 
-public class HostInfo {
+public class HostInfo implements Pojo {
 
     private final String hostname;
     private final String osName;
--- a/common/src/main/java/com/redhat/thermostat/common/model/MemoryStat.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/model/MemoryStat.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,7 +36,7 @@
 
 package com.redhat.thermostat.common.model;
 
-public class MemoryStat {
+public class MemoryStat implements TimeStampedPojo {
     private final long timestamp;
     private final long total;
     private final long free;
@@ -57,6 +57,7 @@
         this.commitLimit = commitLimit;
     }
 
+    @Override
     public long getTimeStamp() {
         return timestamp;
     }
--- a/common/src/main/java/com/redhat/thermostat/common/model/NetworkInterfaceInfo.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/model/NetworkInterfaceInfo.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,7 +36,7 @@
 
 package com.redhat.thermostat.common.model;
 
-public class NetworkInterfaceInfo {
+public class NetworkInterfaceInfo implements Pojo {
 
     private String iFace;
     private String ip4Addr;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/model/Pojo.java	Tue Apr 03 10:22:17 2012 -0400
@@ -0,0 +1,9 @@
+package com.redhat.thermostat.common.model;
+
+/**
+ * All data types should implement this empty interface, to support the
+ * generalization of DAO code where possible.
+ */
+public interface Pojo {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/model/TimeStampedPojo.java	Tue Apr 03 10:22:17 2012 -0400
@@ -0,0 +1,11 @@
+package com.redhat.thermostat.common.model;
+
+/**
+ * Any Pojo which is taken as a timestamped piece of data should
+ * implement this interface.
+ */
+public interface TimeStampedPojo extends Pojo {
+
+    public long getTimeStamp();
+
+}
--- a/common/src/main/java/com/redhat/thermostat/common/model/VmClassStat.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/model/VmClassStat.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,7 +36,7 @@
 
 package com.redhat.thermostat.common.model;
 
-public class VmClassStat {
+public class VmClassStat implements TimeStampedPojo {
 
     private int vmId;
     private long timestamp;
@@ -52,7 +52,8 @@
         return vmId;
     }
 
-    public long getTimestamp() {
+    @Override
+    public long getTimeStamp() {
         return timestamp;
     }
 
--- a/common/src/main/java/com/redhat/thermostat/common/model/VmCpuStat.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/model/VmCpuStat.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,7 +36,7 @@
 
 package com.redhat.thermostat.common.model;
 
-public class VmCpuStat {
+public class VmCpuStat implements TimeStampedPojo {
 
     private final long timestamp;
     private final int vmId;
@@ -48,6 +48,7 @@
         this.cpuLoad = cpuLoad;
     }
 
+    @Override
     public long getTimeStamp() {
         return timestamp;
     }
--- a/common/src/main/java/com/redhat/thermostat/common/model/VmGcStat.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/model/VmGcStat.java	Tue Apr 03 10:22:17 2012 -0400
@@ -36,7 +36,7 @@
 
 package com.redhat.thermostat.common.model;
 
-public class VmGcStat {
+public class VmGcStat implements TimeStampedPojo {
 
     private final long timestamp;
     private final int vmId;
@@ -64,6 +64,7 @@
         return wallTime;
     }
 
+    @Override
     public long getTimeStamp() {
         return timestamp;
     }
--- a/common/src/main/java/com/redhat/thermostat/common/model/VmInfo.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/model/VmInfo.java	Tue Apr 03 10:22:17 2012 -0400
@@ -40,7 +40,7 @@
 import java.util.List;
 import java.util.Map;
 
-public class VmInfo {
+public class VmInfo implements Pojo {
 
     private int vmPid = 0;
     private long startTime = System.currentTimeMillis();
--- a/common/src/main/java/com/redhat/thermostat/common/model/VmMemoryStat.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/model/VmMemoryStat.java	Tue Apr 03 10:22:17 2012 -0400
@@ -38,7 +38,7 @@
 
 import java.util.List;
 
-public class VmMemoryStat {
+public class VmMemoryStat implements TimeStampedPojo {
 
     public static class Generation {
         public static final String COLLECTOR_NONE = "none";
@@ -80,6 +80,7 @@
         return vmId;
     }
 
+    @Override
     public long getTimeStamp() {
         return timestamp;
     }
--- a/common/src/main/java/com/redhat/thermostat/common/storage/Key.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/storage/Key.java	Tue Apr 03 10:22:17 2012 -0400
@@ -45,6 +45,7 @@
     // Keys used by most Categories.
     public static final Key<Long> TIMESTAMP = new Key<>("timestamp", false);
     public static final Key<String> AGENT_ID = new Key<>("agent-id", false);
+    public static final Key<Integer> VM_ID = new Key<>("vm-id", false);
     public static final Key<String> WHERE = new Key<>("$where", false);
 
     private String name;
--- a/common/src/test/java/com/redhat/thermostat/common/dao/CpuStatConverterTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/CpuStatConverterTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -47,9 +47,9 @@
 public class CpuStatConverterTest {
 
     @Test
-    public void testCpuStatToChunk() {
+    public void testToChunk() {
         CpuStat stat = new CpuStat(10, 5.0, 10.0, 15.0);
-        Chunk chunk = new CpuStatConverter().cpuStatToChunk(stat);
+        Chunk chunk = new CpuStatConverter().toChunk(stat);
         assertNotNull(chunk);
         assertEquals("cpu-stats", chunk.getCategory().getName());
         assertEquals((Long) 10L, chunk.get(Key.TIMESTAMP));
@@ -59,13 +59,13 @@
     }
 
     @Test
-    public void testChunkToCpuStat() {
+    public void testFromChunk() {
         Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
         chunk.put(Key.TIMESTAMP, 10L);
         chunk.put(CpuStatDAO.cpu5LoadKey, 5.0);
         chunk.put(CpuStatDAO.cpu10LoadKey, 10.0);
         chunk.put(CpuStatDAO.cpu15LoadKey, 15.0);
-        CpuStat stat = new CpuStatConverter().chunkToCpuStat(chunk);
+        CpuStat stat = new CpuStatConverter().fromChunk(chunk);
         assertNotNull(stat);
         assertEquals(10L, stat.getTimeStamp());
         assertEquals(5.0, stat.getLoad5(), 0.001);
--- a/common/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -88,8 +88,8 @@
         HostRef hostRef = mock(HostRef.class);
         when(hostRef.getAgentId()).thenReturn("system");
 
-        CpuStatDAO dao = new CpuStatDAOImpl(storage, hostRef);
-        List<CpuStat> cpuStats = dao.getLatestCpuStats();
+        CpuStatDAO dao = new CpuStatDAOImpl(storage);
+        List<CpuStat> cpuStats = dao.getLatestCpuStats(hostRef);
 
         ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
         verify(storage).findAll(arg.capture());
@@ -121,9 +121,9 @@
         HostRef hostRef = mock(HostRef.class);
         when(hostRef.getAgentId()).thenReturn("system");
 
-        CpuStatDAO dao = new CpuStatDAOImpl(storage, hostRef);
-        dao.getLatestCpuStats();
-        dao.getLatestCpuStats();
+        CpuStatDAO dao = new CpuStatDAOImpl(storage);
+        dao.getLatestCpuStats(hostRef);
+        dao.getLatestCpuStats(hostRef);
 
         ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
         verify(storage, times(2)).findAll(arg.capture());
--- a/common/src/test/java/com/redhat/thermostat/common/dao/HostInfoConverterTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/HostInfoConverterTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -51,7 +51,7 @@
     public void testHostInfoToChunk() {
         HostInfo info = new HostInfo("a-host", "an-os", "a-kernel", "a-cpu", 9, 99);
 
-        Chunk chunk = new HostInfoConverter().hostInfoToChunk(info);
+        Chunk chunk = new HostInfoConverter().toChunk(info);
 
         assertEquals("host-info", chunk.getCategory().getName());
         assertEquals("a-host", chunk.get(new Key<String>("hostname", true)));
@@ -80,7 +80,7 @@
         chunk.put(HostInfoDAO.cpuCountKey, CPU_NUM);
         chunk.put(HostInfoDAO.hostMemoryTotalKey, MEMORY_TOTAL);
 
-        HostInfo info = new HostInfoConverter().chunkToHostInfo(chunk);
+        HostInfo info = new HostInfoConverter().fromChunk(chunk);
         assertNotNull(info);
         assertEquals(HOST_NAME, info.getHostname());
         assertEquals(OS_NAME, info.getOsName());
--- a/common/src/test/java/com/redhat/thermostat/common/dao/HostInfoDAOTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/HostInfoDAOTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -86,7 +86,7 @@
         Storage storage = mock(Storage.class);
         when(storage.find(any(Chunk.class))).thenReturn(chunk);
 
-        HostInfo info = new HostInfoDAOImpl(storage, new HostRef("some uid", HOST_NAME)).getHostInfo();
+        HostInfo info = new HostInfoDAOImpl(storage).getHostInfo(new HostRef("some uid", HOST_NAME));
         assertNotNull(info);
         assertEquals(HOST_NAME, info.getHostname());
         assertEquals(OS_NAME, info.getOsName());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/HostLatestPojoListGetterTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -0,0 +1,171 @@
+package com.redhat.thermostat.common.dao;
+
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.model.CpuStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+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.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.any;
+
+public class HostLatestPojoListGetterTest {
+    private static final String AGENT_ID = "agentid";
+    private static final String HOSTNAME = "host.example.com";
+    private static final String CATEGORY_NAME = "hostcategory";
+    // Make this one static so we don't get IllegalStateException from trying
+    // to make category of same name while running tests in same classloader.
+    private static final Category cat =  new Category(CATEGORY_NAME);
+
+    private static long t1 = 1;
+    private static long t2 = 5;
+    private static long t3 = 10;
+
+    private static double load5_1 = 2.0;
+    private static double load5_2 = 6.0;
+    private static double load5_3 = 11.0;
+
+    private static double load10_1 = 3.0;
+    private static double load10_2 = 7.0;
+    private static double load10_3 = 12.0;
+
+    private static double load15_1 = 4.0;
+    private static double load15_2 = 8.0;
+    private static double load15_3 = 13.0;
+
+    private HostRef ref;
+    private Converter<CpuStat> converter;
+    private Chunk result1, result2, result3;
+
+    @Before
+    public void setUp() {
+        ref = new HostRef(AGENT_ID, HOSTNAME);
+        converter = new CpuStatConverter();
+        result1 = new Chunk(cat, false);
+        result1.put(Key.AGENT_ID, AGENT_ID);
+        result1.put(Key.TIMESTAMP, t1);
+        result1.put(CpuStatDAO.cpu5LoadKey, load5_1);
+        result1.put(CpuStatDAO.cpu10LoadKey, load10_1);
+        result1.put(CpuStatDAO.cpu15LoadKey, load15_1);
+        result2 = new Chunk(cat, false);
+        result2.put(Key.AGENT_ID, AGENT_ID);
+        result2.put(Key.TIMESTAMP, t2);
+        result2.put(CpuStatDAO.cpu5LoadKey, load5_2);
+        result2.put(CpuStatDAO.cpu10LoadKey, load10_2);
+        result2.put(CpuStatDAO.cpu15LoadKey, load15_2);
+        result3 = new Chunk(cat, false);
+        result3.put(Key.AGENT_ID, AGENT_ID);
+        result3.put(Key.TIMESTAMP, t3);
+        result3.put(CpuStatDAO.cpu5LoadKey, load5_3);
+        result3.put(CpuStatDAO.cpu10LoadKey, load10_3);
+        result3.put(CpuStatDAO.cpu15LoadKey, load15_3);
+    }
+
+    @Test
+    public void testBuildQuery() {
+        Storage storage = mock(Storage.class);
+        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
+        Chunk query = getter.buildQuery();
+
+        assertNotNull(query);
+        assertEquals(cat, query.getCategory());
+        assertEquals(1, query.getKeys().size());
+        assertTrue(query.getKeys().contains(Key.AGENT_ID));
+        assertFalse(query.getKeys().contains(Key.WHERE));
+        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
+    }
+
+    @Test
+    public void testBuildQueryPopulatesUpdateTimes() {
+        Storage storage = mock(Storage.class);
+        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
+        getter.buildQuery(); // Ignore first return value.
+        Chunk query = getter.buildQuery();
+
+        assertNotNull(query);
+        assertEquals(cat, query.getCategory());
+        assertEquals(2, query.getKeys().size());
+        assertTrue(query.getKeys().contains(Key.AGENT_ID));
+        assertTrue(query.getKeys().contains(Key.WHERE));
+        assertEquals("this.timestamp > " + Long.MIN_VALUE, query.get(Key.WHERE));
+    }
+
+    @Test
+    public void testGetLatest() {
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
+
+        List<CpuStat> stats = getter.getLatest();
+
+        assertNotNull(stats);
+        assertEquals(2, stats.size());
+        CpuStat stat1 = stats.get(0);
+        assertEquals(t1, stat1.getTimeStamp());
+        assertEquals(load5_1, stat1.getLoad5(), 0.001);
+        assertEquals(load10_1, stat1.getLoad10(), 0.001);
+        assertEquals(load15_1, stat1.getLoad15(), 0.001);
+        CpuStat stat2 = stats.get(1);
+        assertEquals(t2, stat2.getTimeStamp());
+        assertEquals(load5_2, stat2.getLoad5(), 0.001);
+        assertEquals(load10_2, stat2.getLoad10(), 0.001);
+        assertEquals(load15_2, stat2.getLoad15(), 0.001);
+    }
+
+    @Test
+    public void testGetLatestMultipleCalls() {
+        Cursor cursor1 = mock(Cursor.class);
+        when(cursor1.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(cursor1.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
+
+        Cursor cursor2 = mock(Cursor.class);
+        when(cursor2.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor2.next()).thenReturn(result3);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor1);
+
+        HostLatestPojoListGetter<CpuStat> getter = new HostLatestPojoListGetter<>(storage, cat, converter, ref);
+        getter.getLatest();
+        getter.getLatest();
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage, times(2)).findAll(arg.capture());
+        List<Chunk> queries = arg.getAllValues();
+
+        assertEquals(2, queries.size());
+        Chunk query = queries.get(1);
+        assertNotNull(query);
+        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
+        assertEquals("this.timestamp > " + t2, query.get(Key.WHERE));
+    }
+
+    @After
+    public void tearDown() {
+        ref = null;
+        converter = null;
+        result1 = null;
+        result2 = null;
+        result3 = null;
+    }
+}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/MemoryStatConverterTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/MemoryStatConverterTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -50,7 +50,7 @@
     public void testMemoryStatToChunk() {
         MemoryStat stat = new MemoryStat(0, 1, 2, 3, 4, 5, 6, 7);
 
-        Chunk chunk = new MemoryStatConverter().memoryStatToChunk(stat);
+        Chunk chunk = new MemoryStatConverter().toChunk(stat);
 
         assertEquals((Long) 0l, chunk.get(Key.TIMESTAMP));
         assertEquals((Long) 1l, chunk.get(new Key<Long>("total", false)));
@@ -83,7 +83,7 @@
         chunk.put(MemoryStatDAO.memorySwapFreeKey, SWAP_FREE);
         chunk.put(MemoryStatDAO.memoryCommitLimitKey, COMMIT_LIMIT);
 
-        MemoryStat stat = new MemoryStatConverter().chunkToMemoryStat(chunk);
+        MemoryStat stat = new MemoryStatConverter().fromChunk(chunk);
 
         assertEquals(TIMESTAMP, stat.getTimeStamp());
         assertEquals(TOTAL, stat.getTotal());
--- a/common/src/test/java/com/redhat/thermostat/common/dao/MemoryStatDAOTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/MemoryStatDAOTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -105,8 +105,8 @@
         HostRef hostRef = mock(HostRef.class);
         when(hostRef.getAgentId()).thenReturn("system");
 
-        MemoryStatDAO dao = new MemoryStatDAOImpl(storage, hostRef);
-        List<MemoryStat> memoryStats = dao.getLatestMemoryStats();
+        MemoryStatDAO dao = new MemoryStatDAOImpl(storage);
+        List<MemoryStat> memoryStats = dao.getLatestMemoryStats(hostRef);
 
         ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
         verify(storage).findAll(arg.capture());
@@ -156,9 +156,9 @@
         HostRef hostRef = mock(HostRef.class);
         when(hostRef.getAgentId()).thenReturn("system");
 
-        MemoryStatDAO dao = new MemoryStatDAOImpl(storage, hostRef);
-        dao.getLatestMemoryStats();
-        dao.getLatestMemoryStats();
+        MemoryStatDAO dao = new MemoryStatDAOImpl(storage);
+        dao.getLatestMemoryStats(hostRef);
+        dao.getLatestMemoryStats(hostRef);
 
         ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
         verify(storage, times(2)).findAll(arg.capture());
--- a/common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -73,49 +73,49 @@
 
     @Test
     public void testGetVmClassStatsDAO() {
-        VmClassStatDAO dao = daoFactory.getVmClassStatsDAO(vmRef);
+        VmClassStatDAO dao = daoFactory.getVmClassStatsDAO();
         assertNotNull(dao);
     }
 
     @Test
     public void testGetVmGcStatDAO() {
-        VmGcStatDAO dao = daoFactory.getVmGcStatDAO(vmRef);
+        VmGcStatDAO dao = daoFactory.getVmGcStatDAO();
         assertNotNull(dao);
     }
 
     @Test
     public void testGetVmInfoDAO() {
-        VmInfoDAO dao = daoFactory.getVmInfoDAO(vmRef);
+        VmInfoDAO dao = daoFactory.getVmInfoDAO();
         assertNotNull(dao);
     }
 
     @Test
     public void testGetVmMemoryStatDAO() {
-        VmMemoryStatDAO dao = daoFactory.getVmMemoryStatDAO(vmRef);
+        VmMemoryStatDAO dao = daoFactory.getVmMemoryStatDAO();
         assertNotNull(dao);
     }
 
     @Test
     public void testGetHostInfoDAO() {
-        HostInfoDAO dao = daoFactory.getHostInfoDAO(hostRef);
+        HostInfoDAO dao = daoFactory.getHostInfoDAO();
         assertNotNull(dao);
     }
 
     @Test
     public void testGetCpuStatDAO() {
-        CpuStatDAO dao = daoFactory.getCpuStatDAO(hostRef);
+        CpuStatDAO dao = daoFactory.getCpuStatDAO();
         assertNotNull(dao);
     }
 
     @Test
     public void testGetMemoryStatDAO() {
-        MemoryStatDAO dao = daoFactory.getMemoryStatDAO(hostRef);
+        MemoryStatDAO dao = daoFactory.getMemoryStatDAO();
         assertNotNull(dao);
     }
 
     @Test
     public void testGetNetworkInterfaceInfoDAO() {
-        NetworkInterfaceInfoDAO dao = daoFactory.getNetworkInterfaceInfoDAO(hostRef);
+        NetworkInterfaceInfoDAO dao = daoFactory.getNetworkInterfaceInfoDAO();
         assertNotNull(dao);
     }
 
--- a/common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverterTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoConverterTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -53,7 +53,7 @@
         info.setIp4Addr("4");
         info.setIp6Addr("6");
 
-        Chunk chunk = new NetworkInterfaceInfoConverter().networkInfoToChunk(info);
+        Chunk chunk = new NetworkInterfaceInfoConverter().toChunk(info);
 
         assertEquals("network-info", chunk.getCategory().getName());
         assertEquals("eth0", chunk.get(new Key<String>("iface", true)));
@@ -73,7 +73,7 @@
         chunk.put(NetworkInterfaceInfoDAO.ip4AddrKey, IPV4_ADDR);
         chunk.put(NetworkInterfaceInfoDAO.ip6AddrKey, IPV6_ADDR);
 
-        NetworkInterfaceInfo info = new NetworkInterfaceInfoConverter().chunkToNetworkInfo(chunk);
+        NetworkInterfaceInfo info = new NetworkInterfaceInfoConverter().fromChunk(chunk);
         assertNotNull(info);
         assertEquals(INTERFACE_NAME, info.getInterfaceName());
         assertEquals(IPV4_ADDR, info.getIp4Addr());
--- a/common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/NetworkInterfaceInfoDAOTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -93,8 +93,8 @@
         HostRef hostRef = mock(HostRef.class);
         when(hostRef.getAgentId()).thenReturn("system");
 
-        NetworkInterfaceInfoDAO dao = new NetworkInterfaceInfoDAOImpl(storage, hostRef);
-        List<NetworkInterfaceInfo> netInfo = dao.getNetworkInterfaces();
+        NetworkInterfaceInfoDAO dao = new NetworkInterfaceInfoDAOImpl(storage);
+        List<NetworkInterfaceInfo> netInfo = dao.getNetworkInterfaces(hostRef);
 
         ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
         verify(storage).findAll(arg.capture());
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatConverterTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatConverterTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -51,7 +51,7 @@
         VmClassStat stat = new VmClassStat(123, 1234L, 12345L);
 
         VmClassStatConverter dao = new VmClassStatConverter();
-        Chunk chunk = dao.vmClassStatToChunk(stat);
+        Chunk chunk = dao.toChunk(stat);
 
         assertEquals("vm-class-stats", chunk.getCategory().getName());
         assertEquals((Long) 1234L, chunk.get(Key.TIMESTAMP));
@@ -62,14 +62,14 @@
     @Test
     public void testChunkToVmClassStat() {
         Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
-        chunk.put(VmClassStatDAO.vmIdKey, 123);
+        chunk.put(Key.VM_ID, 123);
         chunk.put(Key.TIMESTAMP, 1234L);
         chunk.put(VmClassStatDAO.loadedClassesKey, 12345L);
 
-        VmClassStat stat = new VmClassStatConverter().chunkToVmClassStat(chunk);
+        VmClassStat stat = new VmClassStatConverter().fromChunk(chunk);
 
         assertEquals(123, stat.getVmId());
-        assertEquals(1234L, stat.getTimestamp());
+        assertEquals(1234L, stat.getTimeStamp());
         assertEquals(12345L, stat.getLoadedClasses());
     }
 }
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -75,7 +75,7 @@
 
         Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
         chunk.put(Key.TIMESTAMP, 1234L);
-        chunk.put(VmClassStatDAO.vmIdKey, 321);
+        chunk.put(Key.VM_ID, 321);
         chunk.put(VmClassStatDAO.loadedClassesKey, 12345L);
 
         Cursor cursor = mock(Cursor.class);
@@ -93,8 +93,8 @@
         when(vmRef.getId()).thenReturn(321);
 
 
-        VmClassStatDAO dao = new VmClassStatDAOImpl(storage, vmRef);
-        List<VmClassStat> vmClassStats = dao.getLatestClassStats();
+        VmClassStatDAO dao = new VmClassStatDAOImpl(storage);
+        List<VmClassStat> vmClassStats = dao.getLatestClassStats(vmRef);
 
         ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
         verify(storage).findAll(arg.capture());
@@ -102,7 +102,7 @@
 
         assertEquals(1, vmClassStats.size());
         VmClassStat stat = vmClassStats.get(0);
-        assertEquals(1234L, stat.getTimestamp());
+        assertEquals(1234L, stat.getTimeStamp());
         assertEquals(12345L, stat.getLoadedClasses());
         assertEquals(321, stat.getVmId());
     }
@@ -112,7 +112,7 @@
 
         Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
         chunk.put(Key.TIMESTAMP, 1234L);
-        chunk.put(VmClassStatDAO.vmIdKey, 321);
+        chunk.put(Key.VM_ID, 321);
         chunk.put(VmClassStatDAO.loadedClassesKey, 12345L);
 
         Cursor cursor = mock(Cursor.class);
@@ -130,10 +130,10 @@
         when(vmRef.getId()).thenReturn(321);
 
 
-        VmClassStatDAO dao = new VmClassStatDAOImpl(storage, vmRef);
-        dao.getLatestClassStats();
+        VmClassStatDAO dao = new VmClassStatDAOImpl(storage);
+        dao.getLatestClassStats(vmRef);
 
-        dao.getLatestClassStats();
+        dao.getLatestClassStats(vmRef);
         ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
         verify(storage, times(2)).findAll(arg.capture());
         assertEquals("this.timestamp > 1234", arg.getValue().get(new Key<String>("$where", false)));
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatConverterTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatConverterTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -54,7 +54,7 @@
     public void testVmCpuStatToChunk() {
 
         VmCpuStat vmCpuStat = new VmCpuStat(TIMESTAMP, VM_ID, PROCESSOR_USAGE);
-        Chunk chunk = new VmCpuStatConverter().vmCpuStatToChunk(vmCpuStat);
+        Chunk chunk = new VmCpuStatConverter().toChunk(vmCpuStat);
         assertNotNull(chunk);
         assertEquals("vm-cpu-stats", chunk.getCategory().getName());
         assertEquals((Long)TIMESTAMP, chunk.get(Key.TIMESTAMP));
@@ -67,10 +67,10 @@
     public void testChunkToVmCpuStat() {
         Chunk chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
         chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(VmCpuStatDAO.vmIdKey, VM_ID);
+        chunk.put(Key.VM_ID, VM_ID);
         chunk.put(VmCpuStatDAO.vmCpuLoadKey, PROCESSOR_USAGE);
 
-        VmCpuStat stat = new VmCpuStatConverter().chunkToVmCpuStat(chunk);
+        VmCpuStat stat = new VmCpuStatConverter().fromChunk(chunk);
         assertNotNull(stat);
         assertEquals(TIMESTAMP, stat.getTimeStamp());
         assertEquals(VM_ID, stat.getVmId());
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -75,7 +75,7 @@
         Chunk chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
         chunk.put(Key.TIMESTAMP, 1234L);
         chunk.put(Key.AGENT_ID, "test-agent-id");
-        chunk.put(VmCpuStatDAO.vmIdKey, 321);
+        chunk.put(Key.VM_ID, 321);
         chunk.put(VmCpuStatDAO.vmCpuLoadKey, 9.9);
 
         Cursor cursor = mock(Cursor.class);
@@ -93,8 +93,8 @@
         when(vmRef.getId()).thenReturn(321);
 
 
-        VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage, vmRef);
-        List<VmCpuStat> vmCpuStats = dao.getLatestVmCpuStats();
+        VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage);
+        List<VmCpuStat> vmCpuStats = dao.getLatestVmCpuStats(vmRef);
 
         ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
         verify(storage).findAll(arg.capture());
@@ -113,7 +113,7 @@
         Chunk chunk = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
         chunk.put(Key.AGENT_ID, "test-agent-id");
         chunk.put(Key.TIMESTAMP, 1234L);
-        chunk.put(VmCpuStatDAO.vmIdKey, 321);
+        chunk.put(Key.VM_ID, 321);
         chunk.put(VmCpuStatDAO.vmCpuLoadKey, 9.9);
 
         Cursor cursor = mock(Cursor.class);
@@ -130,10 +130,10 @@
         when(vmRef.getAgent()).thenReturn(hostRef);
         when(vmRef.getId()).thenReturn(321);
 
-        VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage, vmRef);
-        dao.getLatestVmCpuStats();
+        VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage);
+        dao.getLatestVmCpuStats(vmRef);
 
-        dao.getLatestVmCpuStats();
+        dao.getLatestVmCpuStats(vmRef);
         ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
         verify(storage, times(2)).findAll(arg.capture());
         assertEquals("this.timestamp > 1234", arg.getValue().get(new Key<String>("$where", false)));
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatConverterTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatConverterTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -55,7 +55,7 @@
         final Long WALL_TIME = 9L;
 
         VmGcStat stat = new VmGcStat(VM_ID, TIMESTAMP, COLLECTOR, RUN_COUNT, WALL_TIME);
-        Chunk chunk = new VmGcStatConverter().vmGcStatToChunk(stat);
+        Chunk chunk = new VmGcStatConverter().toChunk(stat);
 
         assertNotNull(chunk);
         assertEquals("vm-gc-stats", chunk.getCategory().getName());
@@ -76,11 +76,11 @@
 
         Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatsCategory, false);
         chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(VmGcStatDAO.vmIdKey, VM_ID);
+        chunk.put(Key.VM_ID, VM_ID);
         chunk.put(VmGcStatDAO.collectorKey, COLLECTOR);
         chunk.put(VmGcStatDAO.runCountKey, RUN_COUNT);
         chunk.put(VmGcStatDAO.wallTimeKey, WALL_TIME);
-        VmGcStat stat = new VmGcStatConverter().chunkToVmGcStat(chunk);
+        VmGcStat stat = new VmGcStatConverter().fromChunk(chunk);
 
         assertNotNull(stat);
         assertEquals(TIMESTAMP, (Long) stat.getTimeStamp());
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -83,7 +83,7 @@
 
         Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatsCategory, false);
         chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(VmGcStatDAO.vmIdKey, VM_ID);
+        chunk.put(Key.VM_ID, VM_ID);
         chunk.put(VmGcStatDAO.collectorKey, COLLECTOR);
         chunk.put(VmGcStatDAO.runCountKey, RUN_COUNT);
         chunk.put(VmGcStatDAO.wallTimeKey, WALL_TIME);
@@ -103,8 +103,8 @@
         when(vmRef.getId()).thenReturn(321);
 
 
-        VmGcStatDAO dao = new VmGcStatDAOImpl(storage, vmRef);
-        List<VmGcStat> vmGcStats = dao.getLatestVmGcStats();
+        VmGcStatDAO dao = new VmGcStatDAOImpl(storage);
+        List<VmGcStat> vmGcStats = dao.getLatestVmGcStats(vmRef);
 
         ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
         verify(storage).findAll(arg.capture());
@@ -130,7 +130,7 @@
 
         Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatsCategory, false);
         chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(VmGcStatDAO.vmIdKey, VM_ID);
+        chunk.put(Key.VM_ID, VM_ID);
         chunk.put(VmGcStatDAO.collectorKey, COLLECTOR);
         chunk.put(VmGcStatDAO.runCountKey, RUN_COUNT);
         chunk.put(VmGcStatDAO.wallTimeKey, WALL_TIME);
@@ -149,10 +149,10 @@
         when(vmRef.getAgent()).thenReturn(hostRef);
         when(vmRef.getId()).thenReturn(321);
 
-        VmGcStatDAO dao = new VmGcStatDAOImpl(storage, vmRef);
-        dao.getLatestVmGcStats();
+        VmGcStatDAO dao = new VmGcStatDAOImpl(storage);
+        dao.getLatestVmGcStats(vmRef);
 
-        dao.getLatestVmGcStats();
+        dao.getLatestVmGcStats(vmRef);
         ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
         verify(storage, times(2)).findAll(arg.capture());
         assertEquals("this.timestamp > 456", arg.getValue().get(new Key<String>("$where", false)));
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmInfoConverterTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmInfoConverterTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -91,7 +91,7 @@
                 vmName, vmInfo, vmVersion, vmArgs,
                 props, env, libs);
 
-        Chunk chunk = new VmInfoConverter().vmInfoToChunk(info);
+        Chunk chunk = new VmInfoConverter().toChunk(info);
 
         assertNotNull(chunk);
         assertEquals((Integer) vmId, chunk.get(VmInfoDAO.vmIdKey));
@@ -130,7 +130,7 @@
         chunk.put(VmInfoDAO.environmentKey, env);
         chunk.put(VmInfoDAO.librariesKey, libs);
 
-        VmInfo info = new VmInfoConverter().chunkToVmInfo(chunk);
+        VmInfo info = new VmInfoConverter().fromChunk(chunk);
 
         assertNotNull(info);
         assertEquals((Integer) vmId, (Integer) info.getVmId());
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmInfoDAOTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmInfoDAOTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -143,8 +143,8 @@
         when(vmRef.getAgent()).thenReturn(hostRef);
         when(vmRef.getId()).thenReturn(321);
 
-        VmInfoDAO dao = new VmInfoDAOImpl(storage, vmRef);
-        VmInfo info = dao.getVmInfo();
+        VmInfoDAO dao = new VmInfoDAOImpl(storage);
+        VmInfo info = dao.getVmInfo(vmRef);
 
         assertNotNull(info);
         assertEquals((Integer) vmId, (Integer) info.getVmId());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmLatestPojoListGetterTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -0,0 +1,154 @@
+package com.redhat.thermostat.common.dao;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.model.VmClassStat;
+import com.redhat.thermostat.common.storage.Category;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+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.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class VmLatestPojoListGetterTest {
+    private static final String AGENT_ID = "agentid";
+    private static final String HOSTNAME = "host.example.com";
+    private static final int VM_PID = 123;
+    private static final String MAIN_CLASS = "Foo.class";
+    private static final String CATEGORY_NAME = "vmcategory";
+    // Make this one static so we don't get IllegalStateException from trying
+    // to make category of same name while running tests in same classloader.
+    private static final Category cat =  new Category(CATEGORY_NAME);
+
+    private static long t1 = 1;
+    private static long t2 = 5;
+    private static long t3 = 10;
+
+    private static long lc1 = 10;
+    private static long lc2 = 20;
+    private static long lc3 = 30;
+
+    private HostRef hostRef;
+    private VmRef vmRef;
+    private Converter<VmClassStat> converter;
+    private Chunk result1, result2, result3;
+
+    @Before
+    public void setUp() {
+        hostRef = new HostRef(AGENT_ID, HOSTNAME);
+        vmRef = new VmRef(hostRef, VM_PID, MAIN_CLASS);
+        converter = new VmClassStatConverter();
+        result1 = new Chunk(cat, false);
+        result1.put(Key.AGENT_ID, AGENT_ID);
+        result1.put(Key.VM_ID, VM_PID);
+        result1.put(Key.TIMESTAMP, t1);
+        result1.put(VmClassStatDAO.loadedClassesKey, lc1);
+        result2 = new Chunk(cat, false);
+        result2.put(Key.AGENT_ID, AGENT_ID);
+        result2.put(Key.VM_ID, VM_PID);
+        result2.put(Key.TIMESTAMP, t2);
+        result2.put(VmClassStatDAO.loadedClassesKey, lc2);
+        result3 = new Chunk(cat, false);
+        result3.put(Key.AGENT_ID, AGENT_ID);
+        result3.put(Key.VM_ID, VM_PID);
+        result3.put(Key.TIMESTAMP, t3);
+        result3.put(VmClassStatDAO.loadedClassesKey, lc3);
+    }
+
+    @Test
+    public void testBuildQuery() {
+        Storage storage = mock(Storage.class);
+        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
+        Chunk query = getter.buildQuery();
+
+        assertNotNull(query);
+        assertEquals(cat, query.getCategory());
+        assertEquals(2, query.getKeys().size());
+        assertTrue(query.getKeys().contains(Key.AGENT_ID));
+        assertTrue(query.getKeys().contains(Key.VM_ID));
+        assertFalse(query.getKeys().contains(Key.WHERE));
+        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
+        assertEquals((Integer) VM_PID, query.get(Key.VM_ID));
+    }
+
+    @Test
+    public void testBuildQueryPopulatesUpdateTimes() {
+        Storage storage = mock(Storage.class);
+        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
+        getter.buildQuery(); // Ignore first return value.
+        Chunk query = getter.buildQuery();
+
+        assertNotNull(query);
+        assertEquals(cat, query.getCategory());
+        assertEquals(3, query.getKeys().size());
+        assertTrue(query.getKeys().contains(Key.AGENT_ID));
+        assertTrue(query.getKeys().contains(Key.VM_ID));
+        assertTrue(query.getKeys().contains(Key.WHERE));
+        assertEquals("this.timestamp > " + Long.MIN_VALUE, query.get(Key.WHERE));
+    }
+
+    @Test
+    public void testGetLatest() {
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
+
+        List<VmClassStat> stats = getter.getLatest();
+
+        assertNotNull(stats);
+        assertEquals(2, stats.size());
+        VmClassStat stat1 = stats.get(0);
+        assertEquals(t1, stat1.getTimeStamp());
+        assertEquals(lc1, stat1.getLoadedClasses());
+        VmClassStat stat2 = stats.get(1);
+        assertEquals(t2, stat2.getTimeStamp());
+        assertEquals(lc2, stat2.getLoadedClasses());
+    }
+
+    @Test
+    public void testGetLatestMultipleCalls() {
+        Cursor cursor1 = mock(Cursor.class);
+        when(cursor1.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(cursor1.next()).thenReturn(result1).thenReturn(result2).thenReturn(null);
+
+        Cursor cursor2 = mock(Cursor.class);
+        when(cursor2.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor2.next()).thenReturn(result3);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor1);
+
+        VmLatestPojoListGetter<VmClassStat> getter = new VmLatestPojoListGetter<>(storage, cat, converter, vmRef);
+        getter.getLatest();
+        getter.getLatest();
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage, times(2)).findAll(arg.capture());
+        List<Chunk> queries = arg.getAllValues();
+
+        assertEquals(2, queries.size());
+        Chunk query = queries.get(1);
+        assertNotNull(query);
+        assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
+        assertEquals((Integer) VM_PID, query.get(Key.VM_ID));
+        assertEquals("this.timestamp > " + t2, query.get(Key.WHERE));
+    }
+}
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatConverterTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatConverterTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -84,7 +84,7 @@
 
         VmMemoryStat stat = new VmMemoryStat(1, 2, generations);
 
-        Chunk chunk = new VmMemoryStatConverter().vmMemoryStatToChunk(stat);
+        Chunk chunk = new VmMemoryStatConverter().toChunk(stat);
 
         assertNotNull(chunk);
         assertEquals((Long) 1l, chunk.get(new Key<Long>("timestamp", false)));
@@ -125,7 +125,7 @@
         Chunk chunk = new Chunk(VmMemoryStatDAO.vmMemoryStatsCategory, false);
 
         chunk.put(Key.TIMESTAMP, TIMESTAMP);
-        chunk.put(VmMemoryStatDAO.vmIdKey, VM_ID);
+        chunk.put(Key.VM_ID, VM_ID);
 
         chunk.put(VmMemoryStatDAO.edenGenKey, "new");
         chunk.put(VmMemoryStatDAO.edenCollectorKey, "new-collector");
@@ -157,7 +157,7 @@
         chunk.put(VmMemoryStatDAO.permCapacityKey, 14l);
         chunk.put(VmMemoryStatDAO.permMaxCapacityKey, 15l);
 
-        VmMemoryStat stat = new VmMemoryStatConverter().chunkToVmMemoryStat(chunk);
+        VmMemoryStat stat = new VmMemoryStatConverter().fromChunk(chunk);
 
         assertNotNull(stat);
         assertEquals(TIMESTAMP, stat.getTimeStamp());
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOTest.java	Mon Apr 02 22:27:05 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOTest.java	Tue Apr 03 10:22:17 2012 -0400
@@ -122,8 +122,8 @@
         when(cursor.limit(any(Integer.class))).thenReturn(cursor);
         when(cursor.hasNext()).thenReturn(false);
 
-        VmMemoryStatDAO impl = new VmMemoryStatDAOImpl(storage, vmRef);
-        impl.getLatestMemoryStat();
+        VmMemoryStatDAO impl = new VmMemoryStatDAOImpl(storage);
+        impl.getLatestMemoryStat(vmRef);
 
         ArgumentCaptor<Key> sortKey = ArgumentCaptor.forClass(Key.class);
         ArgumentCaptor<SortDirection> sortDirection = ArgumentCaptor.forClass(SortDirection.class);
@@ -131,7 +131,7 @@
 
         Chunk query = (Chunk) savedQuery[0];
         assertEquals(AGENT_ID, query.get(Key.AGENT_ID));
-        assertEquals((Integer)VM_ID, query.get(VmMemoryStatDAO.vmIdKey));
+        assertEquals((Integer)VM_ID, query.get(Key.VM_ID));
 
         assertTrue(sortKey.getValue().equals(Key.TIMESTAMP));
         assertTrue(sortDirection.getValue().equals(SortDirection.DESCENDING));
@@ -158,8 +158,8 @@
         Storage storage = mock(Storage.class);
         when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
 
-        VmMemoryStatDAO impl = new VmMemoryStatDAOImpl(storage, vmRef);
-        VmMemoryStat latest = impl.getLatestMemoryStat();
+        VmMemoryStatDAO impl = new VmMemoryStatDAOImpl(storage);
+        VmMemoryStat latest = impl.getLatestMemoryStat(vmRef);
         assertTrue(latest == null);
     }
 }