changeset 152:c1fed4f2c975

Refactor VmGc- and VmMemory-Stat to DAO reviewed-by: omajid, rkennke review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-March/000466.html
author Jon VanAlten <vanaltj@gmail.com>
date Wed, 28 Mar 2012 11:53:44 -0400
parents c55999f78af9
children 8532a3491671
files agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java client/src/main/java/com/redhat/thermostat/client/VmPanelFacadeImpl.java client/src/main/java/com/redhat/thermostat/client/ui/MainWindow.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 common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.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/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/dao/VmRef.java common/src/main/java/com/redhat/thermostat/common/storage/Cursor.java common/src/main/java/com/redhat/thermostat/common/storage/MongoCursor.java common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.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/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/VmMemoryStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/storage/MongoCursorTest.java
diffstat 29 files changed, 615 insertions(+), 312 deletions(-) [+]
line wrap: on
line diff
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatDataExtractor.java	Wed Mar 28 11:53:44 2012 -0400
@@ -36,6 +36,8 @@
 
 package com.redhat.thermostat.backend.system;
 
+import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
+
 import sun.jvmstat.monitor.Monitor;
 import sun.jvmstat.monitor.MonitorException;
 import sun.jvmstat.monitor.MonitoredVm;
@@ -134,7 +136,7 @@
     public String getGenerationCollector(long generation) throws MonitorException {
         Monitor m = vm.findByName("sun.gc.collector." + generation + ".name");
         if (m == null) {
-            throw new IllegalArgumentException("not found");
+            return Generation.COLLECTOR_NONE;
         }
         return (String) m.getValue();
     }
--- a/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/agent/src/main/java/com/redhat/thermostat/backend/system/JvmStatVmListener.java	Wed Mar 28 11:53:44 2012 -0400
@@ -118,12 +118,7 @@
                 g.name = extractor.getGenerationName(generation);
                 g.capacity = extractor.getGenerationCapacity(generation);
                 g.maxCapacity = extractor.getGenerationMaxCapacity(generation);
-                try {
-                    g.collector = extractor.getGenerationCollector(generation);
-                } catch (IllegalArgumentException iae) {
-                    /* no collector for this generation */
-                    g.collector = Generation.COLLECTOR_NONE;
-                }
+                g.collector = extractor.getGenerationCollector(generation);
                 long maxSpaces = extractor.getTotalSpaces(generation);
                 List<Space> spaces = new ArrayList<Space>();
                 g.spaces = spaces;
--- a/client/src/main/java/com/redhat/thermostat/client/VmPanelFacadeImpl.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/VmPanelFacadeImpl.java	Wed Mar 28 11:53:44 2012 -0400
@@ -55,8 +55,8 @@
     public VmPanelFacadeImpl(VmRef vmRef, DB db) {
         overviewController = new VmOverviewController(vmRef, db);
         cpuController = new VmCpuController(vmRef);
-        memoryController = new VmMemoryController(vmRef, db);
-        gcController = new VmGcController(vmRef, db);
+        memoryController = new VmMemoryController(vmRef);
+        gcController = new VmGcController(vmRef);
         classesController = new VmClassStatController(vmRef);
     }
 
--- a/client/src/main/java/com/redhat/thermostat/client/ui/MainWindow.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/MainWindow.java	Wed Mar 28 11:53:44 2012 -0400
@@ -473,7 +473,7 @@
             } else if (value instanceof VmRef) {
                 VmRef vmRef = (VmRef) value;
                 String vmNameHtml= new HtmlTextBuilder().bold(vmRef.getName()).toPartialHtml();
-                String vmIdHtml = new HtmlTextBuilder().bold(vmRef.getId()).toPartialHtml();
+                String vmIdHtml = new HtmlTextBuilder().bold(vmRef.getIdString()).toPartialHtml();
                 HtmlTextBuilder builder = new HtmlTextBuilder()
                     .appendRaw(localize(LocaleResources.TREE_HOST_TOOLTIP_VM_NAME, vmNameHtml))
                     .newLine()
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmGcController.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmGcController.java	Wed Mar 28 11:53:44 2012 -0400
@@ -49,15 +49,12 @@
 import java.util.TreeSet;
 import java.util.concurrent.TimeUnit;
 
-import com.mongodb.BasicDBObject;
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.DBCursor;
-import com.mongodb.DBObject;
 import com.redhat.thermostat.client.AsyncUiFacade;
+import com.redhat.thermostat.client.appctx.ApplicationContext;
 import com.redhat.thermostat.client.locale.LocaleResources;
-import com.redhat.thermostat.common.dao.VmGcStatConverter;
-import com.redhat.thermostat.common.dao.VmMemoryStatConverter;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.VmGcStatDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.model.DiscreteTimeData;
 import com.redhat.thermostat.common.model.VmGcStat;
@@ -69,21 +66,20 @@
     private final VmRef vmRef;
     private final VmGcView view;
 
-    private final DBCollection vmGcStatsCollection;
-    private final DBCollection vmMemoryStatsCollection;
-
-    private final Map<String, Long> collectorSeriesLastUpdateTime = new HashMap<String, Long>();
+    private final VmGcStatDAO gcDao;
+    private final VmMemoryStatDAO memDao;
 
     private final Set<String> addedCollectors = new TreeSet<String>();
 
     private final Timer timer = new Timer();
 
-    public VmGcController(VmRef ref, DB db) {
+    public VmGcController(VmRef ref) {
         this.vmRef = ref;
         this.view = createView();
 
-        vmGcStatsCollection = db.getCollection("vm-gc-stats");
-        vmMemoryStatsCollection = db.getCollection("vm-memory-stats");
+        DAOFactory df = ApplicationContext.getInstance().getDAOFactory();
+        gcDao = df.getVmGcStatDAO(vmRef);
+        memDao = df.getVmMemoryStatDAO(vmRef);
     }
 
     protected VmGcView createView() {
@@ -95,8 +91,7 @@
         timer.scheduleAtFixedRate(new TimerTask() {
             @Override
             public void run() {
-                doUpdateCollectorChartsAsync();
-
+                doUpdateCollectorData();
             }
 
         }, 0, TimeUnit.SECONDS.toMillis(5));
@@ -107,7 +102,7 @@
         for (String name: addedCollectors) {
             view.removeChart(name);
         }
-
+        addedCollectors.clear();
         timer.cancel();
     }
 
@@ -117,70 +112,30 @@
                 collectorName, generationName);
     }
 
-    public String[] getCollectorNames() {
-        BasicDBObject queryObject = new BasicDBObject();
-        queryObject.put("agent-id", vmRef.getAgent().getAgentId());
-        queryObject.put("vm-id", Integer.valueOf(vmRef.getId()));
-        @SuppressWarnings("unchecked")
-        // This is temporary; this will eventually come from a DAO as the correct type.
-        List<String> results = vmGcStatsCollection.distinct("collector", queryObject);
-        List<String> collectorNames = new ArrayList<String>(results);
-
-        return collectorNames.toArray(new String[0]);
-    }
-
-    private void doUpdateCollectorChartsAsync() {
-        String[] collectorNames = getCollectorNames();
-        for (final String name: collectorNames) {
+    private void doUpdateCollectorData() {
+        Map<String, List<DiscreteTimeData<? extends Number>>> dataToAdd = new HashMap<>();
+        for (VmGcStat stat : gcDao.getLatestVmGcStats()) {
+            double walltime = 1.0E-6 * stat.getWallTime();
+            String collector = stat.getCollectorName();
+            List<DiscreteTimeData<? extends Number>> data = dataToAdd.get(collector);
+            if (data == null) {
+                data = new ArrayList<DiscreteTimeData<? extends Number>>();
+                dataToAdd.put(collector, data);
+            }
+            data.add(new DiscreteTimeData<Double>(stat.getTimeStamp(), walltime));
+        }
+        for (Map.Entry<String, List<DiscreteTimeData<? extends Number>>> entry : dataToAdd.entrySet()) {
+            String name = entry.getKey();
             if (!addedCollectors.contains(name)) {
                 view.addChart(name, chartName(name, getCollectorGeneration(name)));
                 addedCollectors.add(name);
             }
-
-            BasicDBObject queryObject = new BasicDBObject();
-            queryObject.put("agent-id", vmRef.getAgent().getAgentId());
-            queryObject.put("vm-id", Integer.valueOf(vmRef.getId()));
-            queryObject.put("collector", name);
-            Long lastTime = collectorSeriesLastUpdateTime.get(name);
-            if (lastTime != null) {
-                queryObject.put("timestamp", new BasicDBObject("$gt", (long) lastTime));
-            }
-
-            DBCursor cursor = vmGcStatsCollection.find(queryObject);
-
-            List<DiscreteTimeData<? extends Number>> toAdd = new ArrayList<>();
-            long lastUpdateTime = Long.MIN_VALUE;
-            for (DBObject dbObj: cursor) {
-                VmGcStat stat = new VmGcStatConverter().fromDBObject(dbObj);
-                lastUpdateTime = Math.max(lastUpdateTime, stat.getTimeStamp());
-                // convert microseconds to seconds
-                double walltime = 1.0E-6 * stat.getWallTime();
-                toAdd.add(new DiscreteTimeData<Double>(stat.getTimeStamp(), walltime));
-
-            }
-            view.addData(name, toAdd);
-            collectorSeriesLastUpdateTime.put(name, lastUpdateTime);
+            view.addData(entry.getKey(), entry.getValue());
         }
     }
 
-    private VmMemoryStat getLatestMemoryStat() {
-        BasicDBObject query = new BasicDBObject();
-        query.put("agent-id", vmRef.getAgent().getAgentId());
-        query.put("vm-id", Integer.valueOf(vmRef.getId()));
-        // TODO ensure timestamp is an indexed column
-        BasicDBObject sortByTimeStamp = new BasicDBObject("timestamp", -1);
-        DBCursor cursor;
-        cursor = vmMemoryStatsCollection.find(query).sort(sortByTimeStamp).limit(1);
-        if (cursor.hasNext()) {
-            DBObject current = cursor.next();
-            return new VmMemoryStatConverter().createVmMemoryStatFromDBObject(current);
-        }
-
-        return null;
-    }
-
     public String getCollectorGeneration(String collectorName) {
-        VmMemoryStat info = getLatestMemoryStat();
+        VmMemoryStat info = memDao.getLatestMemoryStat();
 
         for (Generation g: info.getGenerations()) {
             if (g.collector.equals(collectorName)) {
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmMemoryController.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmMemoryController.java	Wed Mar 28 11:53:44 2012 -0400
@@ -42,13 +42,9 @@
 import java.util.TimerTask;
 import java.util.concurrent.TimeUnit;
 
-import com.mongodb.BasicDBObject;
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.DBCursor;
-import com.mongodb.DBObject;
 import com.redhat.thermostat.client.AsyncUiFacade;
-import com.redhat.thermostat.common.dao.VmMemoryStatConverter;
+import com.redhat.thermostat.client.appctx.ApplicationContext;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.model.VmMemoryStat;
 import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
@@ -58,15 +54,13 @@
 
     private final VmRef vmRef;
     private final VmMemoryView view;
-    private final DBCollection vmMemoryStatsCollection;
+    private final VmMemoryStatDAO dao;
 
     private final Timer timer = new Timer();
 
-    public VmMemoryController(VmRef vmRef, DB db) {
+    public VmMemoryController(VmRef vmRef) {
         this.vmRef = vmRef;
-
-        vmMemoryStatsCollection = db.getCollection("vm-memory-stats");
-
+        dao = ApplicationContext.getInstance().getDAOFactory().getVmMemoryStatDAO(this.vmRef);
         view = createView();
     }
 
@@ -75,7 +69,7 @@
         timer.scheduleAtFixedRate(new TimerTask() {
             @Override
             public void run() {
-                VmMemoryStat info = getLatestMemoryStat();
+                VmMemoryStat info = dao.getLatestMemoryStat();
                 List<Generation> generations = info.getGenerations();
                 for (Generation generation: generations) {
                     List<Space> spaces = generation.spaces;
@@ -89,22 +83,6 @@
         }, 0, TimeUnit.SECONDS.toMillis(5));
     }
 
-    private VmMemoryStat getLatestMemoryStat() {
-        BasicDBObject query = new BasicDBObject();
-        query.put("agent-id", vmRef.getAgent().getAgentId());
-        query.put("vm-id", Integer.valueOf(vmRef.getId()));
-        // TODO ensure timestamp is an indexed column
-        BasicDBObject sortByTimeStamp = new BasicDBObject("timestamp", -1);
-        DBCursor cursor;
-        cursor = vmMemoryStatsCollection.find(query).sort(sortByTimeStamp).limit(1);
-        if (cursor.hasNext()) {
-            DBObject current = cursor.next();
-            return new VmMemoryStatConverter().createVmMemoryStatFromDBObject(current);
-        }
-
-        return null;
-    }
-
     @Override
     public void stop() {
         timer.cancel();
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmOverviewController.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmOverviewController.java	Wed Mar 28 11:53:44 2012 -0400
@@ -81,7 +81,7 @@
             public void run() {
                 BasicDBObject queryObject = new BasicDBObject();
                 queryObject.put("agent-id", vmRef.getAgent().getAgentId());
-                queryObject.put("vm-id", Integer.valueOf(vmRef.getId()));
+                queryObject.put("vm-id", vmRef.getId());
                 DBObject vmInfoObject = vmInfoCollection.findOne(queryObject);
                 view.setVmPid(((Integer) vmInfoObject.get("vm-pid")).toString());
                 long actualStartTime = (Long) vmInfoObject.get("start-time");
--- a/common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java	Wed Mar 28 11:53:44 2012 -0400
@@ -51,6 +51,10 @@
 
     public VmClassStatDAO getVmClassStatsDAO(VmRef ref);
 
+    public VmGcStatDAO getVmGcStatDAO(VmRef ref);
+
+    public VmMemoryStatDAO getVmMemoryStatDAO(VmRef vmRef);
+
     public HostInfoDAO getHostInfoDAO(HostRef ref);
 
     public CpuStatDAO getCpuStatDAO(HostRef ref);
@@ -58,4 +62,5 @@
     public MemoryStatDAO getMemoryStatDAO(HostRef ref);
 
     public NetworkInterfaceInfoDAO getNetworkInterfaceInfoDAO(HostRef hostRef);
+
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java	Wed Mar 28 11:53:44 2012 -0400
@@ -101,4 +101,14 @@
     public NetworkInterfaceInfoDAO getNetworkInterfaceInfoDAO(HostRef ref) {
         return new NetworkInterfaceInfoDAOImpl(storage, ref);
     }
+
+    @Override
+    public VmGcStatDAO getVmGcStatDAO(VmRef ref) {
+        return new VmGcStatDAOImpl(storage, ref);
+    }
+
+    @Override
+    public VmMemoryStatDAO getVmMemoryStatDAO(VmRef ref) {
+        return new VmMemoryStatDAOImpl(storage, ref);
+    }
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatConverter.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatConverter.java	Wed Mar 28 11:53:44 2012 -0400
@@ -49,4 +49,11 @@
         chunk.put(VmClassStatDAO.loadedClassesKey, vmClassStat.getLoadedClasses());
         return chunk;
     }
+
+    public VmClassStat chunkToVmClassStat(Chunk chunk) {
+        long timestamp = chunk.get(Key.TIMESTAMP);
+        long loadedClasses = chunk.get(VmClassStatDAO.loadedClassesKey);
+        int vmId = chunk.get(VmClassStatDAO.vmIdKey);
+        return new VmClassStat(vmId, timestamp, loadedClasses);
+    }
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java	Wed Mar 28 11:53:44 2012 -0400
@@ -62,22 +62,19 @@
         ArrayList<VmClassStat> result = new ArrayList<>();
         Chunk query = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
         query.put(Key.AGENT_ID, ref.getAgent().getAgentId());
-        query.put(VmClassStatDAO.vmIdKey, Integer.valueOf(ref.getId()));
+        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);
         }
         Cursor cursor = storage.findAll(query);
-        long timestamp;
-        long loadedClasses;
+        VmClassStatConverter converter = new VmClassStatConverter();
         while (cursor.hasNext()) {
             Chunk current = cursor.next();
-            timestamp = current.get(Key.TIMESTAMP);
-            loadedClasses = current.get(VmClassStatDAO.loadedClassesKey);
-            int vmId = current.get(VmClassStatDAO.vmIdKey);
-            result.add(new VmClassStat(vmId, timestamp, loadedClasses));
-            lastUpdate = Math.max(timestamp, lastUpdate);
+            VmClassStat stat = converter.chunkToVmClassStat(current);
+            result.add(stat);
+            lastUpdate = Math.max(stat.getTimestamp(), lastUpdate);
         }
 
         return result;
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAOImpl.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmCpuStatDAOImpl.java	Wed Mar 28 11:53:44 2012 -0400
@@ -62,7 +62,7 @@
         ArrayList<VmCpuStat> result = new ArrayList<>();
         Chunk query = new Chunk(VmCpuStatDAO.vmCpuStatCategory, false);
         query.put(Key.AGENT_ID, vmRef.getAgent().getAgentId());
-        query.put(VmCpuStatDAO.vmIdKey, Integer.valueOf(vmRef.getId()));
+        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
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatConverter.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatConverter.java	Wed Mar 28 11:53:44 2012 -0400
@@ -36,7 +36,6 @@
 
 package com.redhat.thermostat.common.dao;
 
-import com.mongodb.DBObject;
 import com.redhat.thermostat.common.model.VmGcStat;
 import com.redhat.thermostat.common.storage.Chunk;
 import com.redhat.thermostat.common.storage.Key;
@@ -46,21 +45,21 @@
     public Chunk vmGcStatToChunk(VmGcStat vmGcStat) {
         Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatsCategory, false);
 
-        chunk.put(VmGcStatDAO.vmGcStatVmIdKey, vmGcStat.getVmId());
+        chunk.put(VmGcStatDAO.vmIdKey, vmGcStat.getVmId());
         chunk.put(Key.TIMESTAMP, vmGcStat.getTimeStamp());
-        chunk.put(VmGcStatDAO.vmGcStatCollectorKey, vmGcStat.getCollectorName());
-        chunk.put(VmGcStatDAO.vmGcStatRunCountKey, vmGcStat.getRunCount());
-        chunk.put(VmGcStatDAO.vmGCstatWallTimeKey, vmGcStat.getWallTime());
+        chunk.put(VmGcStatDAO.collectorKey, vmGcStat.getCollectorName());
+        chunk.put(VmGcStatDAO.runCountKey, vmGcStat.getRunCount());
+        chunk.put(VmGcStatDAO.wallTimeKey, vmGcStat.getWallTime());
 
         return chunk;
     }
 
-    public VmGcStat fromDBObject(DBObject dbObj) {
-        int vmId = (Integer) dbObj.get("vm-id");
-        String collectorName = (String) dbObj.get("collector");
-        long timestamp = (Long) dbObj.get("timestamp");
-        long runCount = (Long) dbObj.get("runtime-count");
-        long wallTime = (Long) dbObj.get("wall-time");
+    public VmGcStat chunkToVmGcStat(Chunk chunk) {
+        int vmId = chunk.get(VmGcStatDAO.vmIdKey);
+        long timestamp = chunk.get(Key.TIMESTAMP);
+        String collectorName = chunk.get(VmGcStatDAO.collectorKey);
+        long runCount = chunk.get(VmGcStatDAO.runCountKey);
+        long wallTime = chunk.get(VmGcStatDAO.wallTimeKey);
 
         return new VmGcStat(vmId, timestamp, collectorName, runCount, wallTime);
     }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAO.java	Wed Mar 28 11:53:44 2012 -0400
@@ -36,19 +36,23 @@
 
 package com.redhat.thermostat.common.dao;
 
+import java.util.List;
+
+import com.redhat.thermostat.common.model.VmGcStat;
 import com.redhat.thermostat.common.storage.Category;
 import com.redhat.thermostat.common.storage.Key;
 
-public class VmGcStatDAO {
+public interface VmGcStatDAO {
 
-    static final Key<Integer> vmGcStatVmIdKey = new Key<>("vm-id", false);
-    static final Key<String> vmGcStatCollectorKey = new Key<>("collector", false);
-    static final Key<Long> vmGcStatRunCountKey = new Key<>("runtime-count", false);
+    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> vmGCstatWallTimeKey = new Key<>("wall-time", false);
+    static final Key<Long> wallTimeKey = new Key<>("wall-time", false);
 
     public static final Category vmGcStatsCategory = new Category("vm-gc-stats",
-            vmGcStatVmIdKey, Key.TIMESTAMP, vmGcStatCollectorKey,
-            vmGcStatRunCountKey, vmGCstatWallTimeKey);
+            vmIdKey, Key.TIMESTAMP, collectorKey,
+            runCountKey, wallTimeKey);
 
+    public List<VmGcStat> getLatestVmGcStats();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmGcStatDAOImpl.java	Wed Mar 28 11:53:44 2012 -0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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 {
+
+    private Storage storage;
+    private VmRef ref;
+
+    private long lastUpdate = Long.MIN_VALUE;
+
+    public VmGcStatDAOImpl(Storage storage, VmRef ref) {
+        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);
+        }
+        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;
+    }
+
+}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatConverter.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatConverter.java	Wed Mar 28 11:53:44 2012 -0400
@@ -55,86 +55,127 @@
         chunk.put(Key.TIMESTAMP, vmMemStat.getTimeStamp());
 
         Generation newGen = vmMemStat.getGeneration("new");
+
         Space eden = newGen.getSpace("eden");
-
-        chunk.put(VmMemoryStatDAO.vmMemoryStatEdenGenKey, newGen.name);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatEdenCollectorKey, newGen.collector);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatEdenCapacityKey, eden.capacity);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatEdenMaxCapacityKey, eden.maxCapacity);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatEdenUsedKey, eden.used);
+        chunk.put(VmMemoryStatDAO.edenGenKey, newGen.name);
+        chunk.put(VmMemoryStatDAO.edenCollectorKey, newGen.collector);
+        chunk.put(VmMemoryStatDAO.edenCapacityKey, eden.capacity);
+        chunk.put(VmMemoryStatDAO.edenMaxCapacityKey, eden.maxCapacity);
+        chunk.put(VmMemoryStatDAO.edenUsedKey, eden.used);
 
         Space s0 = newGen.getSpace("s0");
-        chunk.put(VmMemoryStatDAO.vmMemoryStatS0GenKey, newGen.name);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatS0CollectorKey, newGen.collector);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatS0CapacityKey, s0.capacity);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatS0MaxCapacityKey, s0.maxCapacity);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatS0UsedKey, s0.used);
+        chunk.put(VmMemoryStatDAO.s0GenKey, newGen.name);
+        chunk.put(VmMemoryStatDAO.s0CollectorKey, newGen.collector);
+        chunk.put(VmMemoryStatDAO.s0CapacityKey, s0.capacity);
+        chunk.put(VmMemoryStatDAO.s0MaxCapacityKey, s0.maxCapacity);
+        chunk.put(VmMemoryStatDAO.s0UsedKey, s0.used);
 
         Space s1 = newGen.getSpace("s1");
-        chunk.put(VmMemoryStatDAO.vmMemoryStatS1GenKey, newGen.name);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatS1CollectorKey, newGen.collector);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatS1CapacityKey, s1.capacity);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatS1MaxCapacityKey, s1.maxCapacity);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatS1UsedKey, s1.used);
+        chunk.put(VmMemoryStatDAO.s1GenKey, newGen.name);
+        chunk.put(VmMemoryStatDAO.s1CollectorKey, newGen.collector);
+        chunk.put(VmMemoryStatDAO.s1CapacityKey, s1.capacity);
+        chunk.put(VmMemoryStatDAO.s1MaxCapacityKey, s1.maxCapacity);
+        chunk.put(VmMemoryStatDAO.s1UsedKey, s1.used);
 
         Generation oldGen = vmMemStat.getGeneration("old");
+
         Space old = oldGen.getSpace("old");
-
-        chunk.put(VmMemoryStatDAO.vmMemoryStatOldGenKey, oldGen.name);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatOldCollectorKey, oldGen.collector);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatOldCapacityKey, old.capacity);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatOldMaxCapacityKey, old.maxCapacity);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatOldUsedKey, old.used);
+        chunk.put(VmMemoryStatDAO.oldGenKey, oldGen.name);
+        chunk.put(VmMemoryStatDAO.oldCollectorKey, oldGen.collector);
+        chunk.put(VmMemoryStatDAO.oldCapacityKey, old.capacity);
+        chunk.put(VmMemoryStatDAO.oldMaxCapacityKey, old.maxCapacity);
+        chunk.put(VmMemoryStatDAO.oldUsedKey, old.used);
 
         Generation permGen = vmMemStat.getGeneration("perm");
+
         Space perm = permGen.getSpace("perm");
-
-        chunk.put(VmMemoryStatDAO.vmMemoryStatPermGenKey, permGen.name);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatPermCollectorKey, permGen.collector);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatPermCapacityKey, perm.capacity);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatPermMaxCapacityKey, perm.maxCapacity);
-        chunk.put(VmMemoryStatDAO.vmMemoryStatPermUsedKey, perm.used);
+        chunk.put(VmMemoryStatDAO.permGenKey, permGen.name);
+        chunk.put(VmMemoryStatDAO.permCollectorKey, permGen.collector);
+        chunk.put(VmMemoryStatDAO.permCapacityKey, perm.capacity);
+        chunk.put(VmMemoryStatDAO.permMaxCapacityKey, perm.maxCapacity);
+        chunk.put(VmMemoryStatDAO.permUsedKey, perm.used);
 
         return chunk;
     }
 
-    public VmMemoryStat createVmMemoryStatFromDBObject(DBObject dbObj) {
-        // FIXME so much hardcoding :'(
+    public VmMemoryStat chunkToVmMemoryStat(Chunk chunk) {
+        Space space = null;
+        List<Space> spaces = null;
+
+        List<Generation> gens = new ArrayList<>();
+        Generation newGen = new Generation();
+        spaces = new ArrayList<>();
+        newGen.spaces = spaces;
+        newGen.name = "new";
+        newGen.capacity = 0;
+        newGen.maxCapacity = 0;
+        // FIXME Something is wrong here when we have the collector stored
+        // as part of 3 spaces in Chunk but is only one thing in Stat
+        newGen.collector = chunk.get(VmMemoryStatDAO.edenCollectorKey);
 
-        String[] spaceNames = new String[] { "eden", "s0", "s1", "old", "perm" };
-        List<Generation> generations = new ArrayList<Generation>();
+        space = new Space();
+        space.name = chunk.get(VmMemoryStatDAO.edenGenKey);
+        space.capacity = chunk.get(VmMemoryStatDAO.edenCapacityKey);
+        space.maxCapacity = chunk.get(VmMemoryStatDAO.edenMaxCapacityKey);
+        space.used = chunk.get(VmMemoryStatDAO.edenUsedKey);
+        spaces.add(space);
+        newGen.capacity += space.capacity;
+        newGen.maxCapacity += space.maxCapacity;
+
+        space = new Space();
+        space.name = chunk.get(VmMemoryStatDAO.s0GenKey);
+        space.capacity = chunk.get(VmMemoryStatDAO.s0CapacityKey);
+        space.maxCapacity = chunk.get(VmMemoryStatDAO.s0MaxCapacityKey);
+        space.used = chunk.get(VmMemoryStatDAO.s0UsedKey);
+        spaces.add(space);
+        newGen.capacity += space.capacity;
+        newGen.maxCapacity += space.maxCapacity;
 
-        long timestamp = (Long) dbObj.get("timestamp");
-        int vmId = (Integer) dbObj.get("vm-id");
-        for (String spaceName: spaceNames) {
-            DBObject info = (DBObject) dbObj.get(spaceName);
-            String generationName = (String) info.get("gen");
-            Generation target = null;
-            for (Generation generation: generations) {
-                if (generation.name.equals(generationName)) {
-                    target = generation;
-                }
-            }
-            if (target == null) {
-                target = new Generation();
-                target.name = generationName;
-                generations.add(target);
-            }
-            if (target.collector == null) {
-                target.collector = (String) info.get("collector");
-            }
-            Space space = new Space();
-            space.name = spaceName;
-            space.capacity = (Long) info.get("capacity");
-            space.maxCapacity = (Long) info.get("max-capacity");
-            space.used = (Long) info.get("used");
-            if (target.spaces == null) {
-                target.spaces = new ArrayList<Space>();
-            }
-            target.spaces.add(space);
-        }
+        space = new Space();
+        space.name = chunk.get(VmMemoryStatDAO.s1GenKey);
+        space.capacity = chunk.get(VmMemoryStatDAO.s1CapacityKey);
+        space.maxCapacity = chunk.get(VmMemoryStatDAO.s1MaxCapacityKey);
+        space.used = chunk.get(VmMemoryStatDAO.s1UsedKey);
+        spaces.add(space);
+        newGen.capacity += space.capacity;
+        newGen.maxCapacity += space.maxCapacity;
+
+        gens.add(newGen);
+
+        Generation oldGen = new Generation();
+        spaces = new ArrayList<>();
+        oldGen.spaces = spaces;
+        oldGen.name = "old";
+        oldGen.collector = chunk.get(VmMemoryStatDAO.oldCollectorKey);
 
-        return new VmMemoryStat(timestamp, vmId, generations);
+        space = new Space();
+        space.name = chunk.get(VmMemoryStatDAO.oldGenKey);
+        space.capacity = chunk.get(VmMemoryStatDAO.oldCapacityKey);
+        space.maxCapacity = chunk.get(VmMemoryStatDAO.oldMaxCapacityKey);
+        space.used = chunk.get(VmMemoryStatDAO.oldUsedKey);
+        spaces.add(space);
+        oldGen.capacity = space.capacity;
+        oldGen.maxCapacity = space.capacity;
+
+        gens.add(oldGen);
+
+        Generation permGen = new Generation();
+        spaces = new ArrayList<>();
+        permGen.spaces = spaces;
+        permGen.name = "perm";
+        permGen.collector = chunk.get(VmMemoryStatDAO.permCollectorKey);
+
+        space = new Space();
+        space.name = chunk.get(VmMemoryStatDAO.permGenKey);
+        space.capacity = chunk.get(VmMemoryStatDAO.permCapacityKey);
+        space.maxCapacity = chunk.get(VmMemoryStatDAO.permMaxCapacityKey);
+        space.used = chunk.get(VmMemoryStatDAO.permUsedKey);
+        spaces.add(space);
+        permGen.capacity = space.capacity;
+        permGen.maxCapacity = space.capacity;
+
+        gens.add(permGen);
+
+        return new VmMemoryStat(chunk.get(Key.TIMESTAMP), chunk.get(VmMemoryStatDAO.vmIdKey), gens);
     }
-
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java	Wed Mar 28 11:53:44 2012 -0400
@@ -40,53 +40,53 @@
 import com.redhat.thermostat.common.storage.Category;
 import com.redhat.thermostat.common.storage.Key;
 
-public abstract class VmMemoryStatDAO {
+public interface VmMemoryStatDAO {
 
     static final Key<Integer> vmIdKey = new Key<>("vm-id", false);
 
-    static final Key<String> vmMemoryStatEdenGenKey = new Key<>("eden.gen", false);
-    static final Key<String> vmMemoryStatEdenCollectorKey = new Key<>("eden.collector", false);
-    static final Key<Long> vmMemoryStatEdenCapacityKey = new Key<>("eden.capacity", false);
-    static final Key<Long> vmMemoryStatEdenMaxCapacityKey = new Key<>("eden.max-capacity", false);
-    static final Key<Long> vmMemoryStatEdenUsedKey = new Key<>("eden.used", 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);
+    static final Key<Long> edenMaxCapacityKey = new Key<>("eden.max-capacity", false);
+    static final Key<Long> edenUsedKey = new Key<>("eden.used", false);
 
-    static final Key<String> vmMemoryStatS0GenKey = new Key<>("s0.gen", false);
-    static final Key<String> vmMemoryStatS0CollectorKey = new Key<>("s0.collector", false);
-    static final Key<Long> vmMemoryStatS0CapacityKey = new Key<>("s0.capacity", false);
-    static final Key<Long> vmMemoryStatS0MaxCapacityKey = new Key<>("s0.max-capacity", false);
-    static final Key<Long> vmMemoryStatS0UsedKey = new Key<>("s0.used", false);
+    static final Key<String> s0GenKey = new Key<>("s0.gen", false);
+    static final Key<String> s0CollectorKey = new Key<>("s0.collector", false);
+    static final Key<Long> s0CapacityKey = new Key<>("s0.capacity", false);
+    static final Key<Long> s0MaxCapacityKey = new Key<>("s0.max-capacity", false);
+    static final Key<Long> s0UsedKey = new Key<>("s0.used", false);
 
-    static final Key<String> vmMemoryStatS1GenKey = new Key<>("s1.gen", false);
-    static final Key<String> vmMemoryStatS1CollectorKey = new Key<>("s1.collector", false);
-    static final Key<Long> vmMemoryStatS1CapacityKey = new Key<>("s1.capacity", false);
-    static final Key<Long> vmMemoryStatS1MaxCapacityKey = new Key<>("s1.max-capacity", false);
-    static final Key<Long> vmMemoryStatS1UsedKey = new Key<>("s1.used", false);
+    static final Key<String> s1GenKey = new Key<>("s1.gen", false);
+    static final Key<String> s1CollectorKey = new Key<>("s1.collector", false);
+    static final Key<Long> s1CapacityKey = new Key<>("s1.capacity", false);
+    static final Key<Long> s1MaxCapacityKey = new Key<>("s1.max-capacity", false);
+    static final Key<Long> s1UsedKey = new Key<>("s1.used", false);
 
-    static final Key<String> vmMemoryStatOldGenKey = new Key<>("old.gen", false);
-    static final Key<String> vmMemoryStatOldCollectorKey = new Key<>("old.collector", false);
-    static final Key<Long> vmMemoryStatOldCapacityKey = new Key<>("old.capacity", false);
-    static final Key<Long> vmMemoryStatOldMaxCapacityKey = new Key<>("old.max-capacity", false);
-    static final Key<Long> vmMemoryStatOldUsedKey = new Key<>("old.used", false);
+    static final Key<String> oldGenKey = new Key<>("old.gen", false);
+    static final Key<String> oldCollectorKey = new Key<>("old.collector", false);
+    static final Key<Long> oldCapacityKey = new Key<>("old.capacity", false);
+    static final Key<Long> oldMaxCapacityKey = new Key<>("old.max-capacity", false);
+    static final Key<Long> oldUsedKey = new Key<>("old.used", false);
 
-    static final Key<String> vmMemoryStatPermGenKey = new Key<>("perm.gen", false);
-    static final Key<String> vmMemoryStatPermCollectorKey = new Key<>("perm.collector", false);
-    static final Key<Long> vmMemoryStatPermCapacityKey = new Key<>("perm.capacity", false);
-    static final Key<Long> vmMemoryStatPermMaxCapacityKey = new Key<>("perm.max-capacity", false);
-    static final Key<Long> vmMemoryStatPermUsedKey = new Key<>("perm.used", false);
+    static final Key<String> permGenKey = new Key<>("perm.gen", false);
+    static final Key<String> permCollectorKey = new Key<>("perm.collector", false);
+    static final Key<Long> permCapacityKey = new Key<>("perm.capacity", false);
+    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,
-            vmMemoryStatEdenGenKey, vmMemoryStatEdenCollectorKey,
-            vmMemoryStatEdenCapacityKey, vmMemoryStatEdenMaxCapacityKey,vmMemoryStatEdenUsedKey,
-            vmMemoryStatS0GenKey, vmMemoryStatS0CollectorKey, vmMemoryStatS0CapacityKey,
-            vmMemoryStatS0MaxCapacityKey, vmMemoryStatS0UsedKey,
-            vmMemoryStatS1GenKey, vmMemoryStatS1CollectorKey, vmMemoryStatS1CapacityKey,
-            vmMemoryStatS1MaxCapacityKey, vmMemoryStatS1UsedKey,
-            vmMemoryStatOldGenKey, vmMemoryStatOldCollectorKey, vmMemoryStatOldCapacityKey,
-            vmMemoryStatOldMaxCapacityKey, vmMemoryStatOldUsedKey,
-            vmMemoryStatPermGenKey, vmMemoryStatPermCollectorKey, vmMemoryStatPermCapacityKey,
-            vmMemoryStatPermMaxCapacityKey, vmMemoryStatPermUsedKey);
+            edenGenKey, edenCollectorKey,
+            edenCapacityKey, edenMaxCapacityKey,edenUsedKey,
+            s0GenKey, s0CollectorKey, s0CapacityKey,
+            s0MaxCapacityKey, s0UsedKey,
+            s1GenKey, s1CollectorKey, s1CapacityKey,
+            s1MaxCapacityKey, s1UsedKey,
+            oldGenKey, oldCollectorKey, oldCapacityKey,
+            oldMaxCapacityKey, oldUsedKey,
+            permGenKey, permCollectorKey, permCapacityKey,
+            permMaxCapacityKey, permUsedKey);
 
-    public abstract VmMemoryStat getLatestMemoryStat();
+    public VmMemoryStat getLatestMemoryStat();
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAOImpl.java	Wed Mar 28 11:53:44 2012 -0400
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.dao;
+
+import com.redhat.thermostat.common.model.VmMemoryStat;
+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 VmMemoryStatDAOImpl implements VmMemoryStatDAO {
+
+    private final Storage storage;
+    private final VmRef ref;
+
+    public VmMemoryStatDAOImpl(Storage storage, VmRef ref) {
+        this.storage = storage;
+        this.ref = ref;
+    }
+
+    @Override
+    public VmMemoryStat getLatestMemoryStat() {
+        Chunk query = new Chunk(VmMemoryStatDAO.vmMemoryStatsCategory, false);
+        query.put(Key.AGENT_ID, ref.getAgent().getAgentId());
+        query.put(VmMemoryStatDAO.vmIdKey, ref.getId());
+        Cursor cursor = storage.findAll(query).sort(Key.AGENT_ID, Cursor.SortDirection.DESCENDING).limit(1);
+        return new VmMemoryStatConverter().chunkToVmMemoryStat(cursor.next());
+    }
+
+}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmRef.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmRef.java	Wed Mar 28 11:53:44 2012 -0400
@@ -39,12 +39,14 @@
 public class VmRef implements Ref {
 
     private final HostRef hostRef;
-    private final String uid;
+    private final Integer uid;
+    private final String uidString;
     private final String name;
 
     public VmRef(HostRef hostRef, Integer id, String name) {
         this.hostRef = hostRef;
-        this.uid = id.toString();
+        this.uid = id;
+        this.uidString = id.toString();
         this.name = name;
     }
 
@@ -57,10 +59,14 @@
         return hostRef;
     }
 
-    public String getId() {
+    public Integer getId() {
         return uid;
     }
 
+    public String getIdString() {
+        return uidString;
+    }
+
     public String getName() {
         return name;
     }
@@ -94,6 +100,6 @@
 
     @Override
     public boolean matches(String filter) {
-        return getName().contains(filter) || getId().contains(filter);
+        return getName().contains(filter) || getIdString().contains(filter);
     }
 }
--- a/common/src/main/java/com/redhat/thermostat/common/storage/Cursor.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/storage/Cursor.java	Wed Mar 28 11:53:44 2012 -0400
@@ -38,11 +38,26 @@
 
 public interface Cursor {
 
+    public enum SortDirection {
+        ASCENDING(1),
+        DESCENDING(-1);
+
+        private int value;
+
+        private SortDirection(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
     boolean hasNext();
 
     Chunk next();
 
-    Cursor sort(Chunk orderBy);
+    Cursor sort(Key<?> orderBy, SortDirection direction);
 
     Cursor limit(int i);
 }
--- a/common/src/main/java/com/redhat/thermostat/common/storage/MongoCursor.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/main/java/com/redhat/thermostat/common/storage/MongoCursor.java	Wed Mar 28 11:53:44 2012 -0400
@@ -36,6 +36,7 @@
 
 package com.redhat.thermostat.common.storage;
 
+import com.mongodb.BasicDBObject;
 import com.mongodb.DBCursor;
 import com.mongodb.DBObject;
 
@@ -65,9 +66,14 @@
     }
 
     @Override
-    public Cursor sort(Chunk orderBy) {
-        ChunkConverter chunkConverter = new ChunkConverter();
-        DBObject dbOrderBy = chunkConverter.chunkToDBObject(orderBy);
+    public Cursor sort(Key<?> orderBy, SortDirection direction) {
+        if (!category.getKeys().contains(orderBy)) {
+            throw new IllegalArgumentException("Key not present in this Cursor's category.");
+        }   /* TODO: There are other possible error conditions.  Once there is API to configure
+             * indexing/optimization, we may want to prevent or log predictably bad performance
+             * sorting requests.
+             */
+        DBObject dbOrderBy = new BasicDBObject(orderBy.getName(), direction.getValue());
         DBCursor sorted = cursor.sort(dbOrderBy);
         return new MongoCursor(sorted, category);
     }
--- a/common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java	Wed Mar 28 11:53:44 2012 -0400
@@ -73,8 +73,20 @@
 
     @Test
     public void testGetVmClassStatsDAO() {
-        VmClassStatDAO vmClassStatsDAO = daoFactory.getVmClassStatsDAO(vmRef);
-        assertNotNull(vmClassStatsDAO);
+        VmClassStatDAO dao = daoFactory.getVmClassStatsDAO(vmRef);
+        assertNotNull(dao);
+    }
+
+    @Test
+    public void testGetVmGcStatDAO() {
+        VmGcStatDAO dao = daoFactory.getVmGcStatDAO(vmRef);
+        assertNotNull(dao);
+    }
+
+    @Test
+    public void testGetVmMemoryStatDAO() {
+        VmMemoryStatDAO dao = daoFactory.getVmMemoryStatDAO(vmRef);
+        assertNotNull(dao);
     }
 
     @Test
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatConverterTest.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatConverterTest.java	Wed Mar 28 11:53:44 2012 -0400
@@ -59,5 +59,17 @@
         assertEquals((Long) 12345L, chunk.get(new Key<Long>("loadedClasses", false)));
     }
 
-    // TODO test conversion the other way too
+    @Test
+    public void testChunkToVmClassStat() {
+        Chunk chunk = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
+        chunk.put(VmClassStatDAO.vmIdKey, 123);
+        chunk.put(Key.TIMESTAMP, 1234L);
+        chunk.put(VmClassStatDAO.loadedClassesKey, 12345L);
+
+        VmClassStat stat = new VmClassStatConverter().chunkToVmClassStat(chunk);
+
+        assertEquals(123, stat.getVmId());
+        assertEquals(1234L, stat.getTimestamp());
+        assertEquals(12345L, stat.getLoadedClasses());
+    }
 }
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmClassStatDAOTest.java	Wed Mar 28 11:53:44 2012 -0400
@@ -90,7 +90,7 @@
 
         VmRef vmRef = mock(VmRef.class);
         when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn("321");
+        when(vmRef.getId()).thenReturn(321);
 
 
         VmClassStatDAO dao = new VmClassStatDAOImpl(storage, vmRef);
@@ -127,7 +127,7 @@
 
         VmRef vmRef = mock(VmRef.class);
         when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn("321");
+        when(vmRef.getId()).thenReturn(321);
 
 
         VmClassStatDAO dao = new VmClassStatDAOImpl(storage, vmRef);
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmCpuStatDAOTest.java	Wed Mar 28 11:53:44 2012 -0400
@@ -90,7 +90,7 @@
 
         VmRef vmRef = mock(VmRef.class);
         when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn("321");
+        when(vmRef.getId()).thenReturn(321);
 
 
         VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage, vmRef);
@@ -128,7 +128,7 @@
 
         VmRef vmRef = mock(VmRef.class);
         when(vmRef.getAgent()).thenReturn(hostRef);
-        when(vmRef.getId()).thenReturn("321");
+        when(vmRef.getId()).thenReturn(321);
 
         VmCpuStatDAO dao = new VmCpuStatDAOImpl(storage, vmRef);
         dao.getLatestVmCpuStats();
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatConverterTest.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatConverterTest.java	Wed Mar 28 11:53:44 2012 -0400
@@ -48,19 +48,45 @@
 
     @Test
     public void testVmGcStatToChunk() {
-        final long RUN_COUNT = 10;
-        final long WALL_TIME = 9;
-        VmGcStat stat = new VmGcStat(123, 456, "collector1", RUN_COUNT, WALL_TIME);
+        final Integer VM_ID = 123;
+        final Long TIMESTAMP = 456L;
+        final String COLLECTOR = "collector1";
+        final Long RUN_COUNT = 10L;
+        final Long WALL_TIME = 9L;
+
+        VmGcStat stat = new VmGcStat(VM_ID, TIMESTAMP, COLLECTOR, RUN_COUNT, WALL_TIME);
         Chunk chunk = new VmGcStatConverter().vmGcStatToChunk(stat);
+
         assertNotNull(chunk);
         assertEquals("vm-gc-stats", chunk.getCategory().getName());
-        assertEquals((Long)456L, chunk.get(new Key<Long>("timestamp", false)));
-        assertEquals((Integer)123, chunk.get(new Key<Integer>("vm-id", false)));
-        assertEquals("collector1", chunk.get(new Key<String>("collector", false)));
-        assertEquals((Long)RUN_COUNT, chunk.get(new Key<Long>("runtime-count", false)));
-        assertEquals((Long)WALL_TIME, chunk.get(new Key<Long>("wall-time", false)));
-
+        assertEquals(TIMESTAMP, chunk.get(new Key<Long>("timestamp", false)));
+        assertEquals(VM_ID, chunk.get(new Key<Integer>("vm-id", false)));
+        assertEquals(COLLECTOR, chunk.get(new Key<String>("collector", false)));
+        assertEquals(RUN_COUNT, chunk.get(new Key<Long>("runtime-count", false)));
+        assertEquals(WALL_TIME, chunk.get(new Key<Long>("wall-time", false)));
     }
 
-    // TODO test conversion the other way too
+    @Test
+    public void testChunkToVmGcStat() {
+        final Integer VM_ID = 123;
+        final Long TIMESTAMP = 456L;
+        final String COLLECTOR = "collector1";
+        final Long RUN_COUNT = 10L;
+        final Long WALL_TIME = 9L;
+
+        Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatsCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(VmGcStatDAO.vmIdKey, 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);
+
+        assertNotNull(stat);
+        assertEquals(TIMESTAMP, (Long) stat.getTimeStamp());
+        assertEquals(VM_ID, (Integer) stat.getVmId());
+        assertEquals(COLLECTOR, stat.getCollectorName());
+        assertEquals(RUN_COUNT, (Long) stat.getRunCount());
+        assertEquals(WALL_TIME, (Long) stat.getWallTime());
+    }
 }
--- a/common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmGcStatDAOTest.java	Wed Mar 28 11:53:44 2012 -0400
@@ -37,13 +37,26 @@
 package com.redhat.thermostat.common.dao;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.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;
+
 
 import java.util.Collection;
+import java.util.List;
 
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
 
+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 VmGcStatDAOTest {
 
@@ -57,6 +70,91 @@
         assertTrue(keys.contains(new Key<Long>("runtime-count", false)));
         assertTrue(keys.contains(new Key<Long>("wall-time", false)));
         assertEquals(5, keys.size());
+    }
 
+    @Test
+    public void testGetLatestVmGcStatsBasic() {
+
+        final Integer VM_ID = 123;
+        final Long TIMESTAMP = 456L;
+        final String COLLECTOR = "collector1";
+        final Long RUN_COUNT = 10L;
+        final Long WALL_TIME = 9L;
+
+        Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatsCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(VmGcStatDAO.vmIdKey, VM_ID);
+        chunk.put(VmGcStatDAO.collectorKey, COLLECTOR);
+        chunk.put(VmGcStatDAO.runCountKey, RUN_COUNT);
+        chunk.put(VmGcStatDAO.wallTimeKey, WALL_TIME);
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(321);
+
+
+        VmGcStatDAO dao = new VmGcStatDAOImpl(storage, vmRef);
+        List<VmGcStat> vmGcStats = dao.getLatestVmGcStats();
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).findAll(arg.capture());
+        assertNull(arg.getValue().get(new Key<String>("$where", false)));
+
+        assertEquals(1, vmGcStats.size());
+        VmGcStat stat = vmGcStats.get(0);
+        assertEquals(TIMESTAMP, (Long) stat.getTimeStamp());
+        assertEquals(VM_ID, (Integer) stat.getVmId());
+        assertEquals(COLLECTOR, stat.getCollectorName());
+        assertEquals(RUN_COUNT, (Long) stat.getRunCount());
+        assertEquals(WALL_TIME, (Long) stat.getWallTime());
+    }
+
+    @Test
+    public void testGetLatestVmGcStatsTwice() {
+
+        final Integer VM_ID = 123;
+        final Long TIMESTAMP = 456L;
+        final String COLLECTOR = "collector1";
+        final Long RUN_COUNT = 10L;
+        final Long WALL_TIME = 9L;
+
+        Chunk chunk = new Chunk(VmGcStatDAO.vmGcStatsCategory, false);
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(VmGcStatDAO.vmIdKey, VM_ID);
+        chunk.put(VmGcStatDAO.collectorKey, COLLECTOR);
+        chunk.put(VmGcStatDAO.runCountKey, RUN_COUNT);
+        chunk.put(VmGcStatDAO.wallTimeKey, WALL_TIME);
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getAgent()).thenReturn(hostRef);
+        when(vmRef.getId()).thenReturn(321);
+
+        VmGcStatDAO dao = new VmGcStatDAOImpl(storage, vmRef);
+        dao.getLatestVmGcStats();
+
+        dao.getLatestVmGcStats();
+        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/VmMemoryStatConverterTest.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/VmMemoryStatConverterTest.java	Wed Mar 28 11:53:44 2012 -0400
@@ -43,7 +43,6 @@
 
 import org.junit.Test;
 
-import com.mongodb.BasicDBObject;
 import com.redhat.thermostat.common.model.VmMemoryStat;
 import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
 import com.redhat.thermostat.common.model.VmMemoryStat.Space;
@@ -119,55 +118,46 @@
     }
 
     @Test
-    public void testDBObjectToVmMemoryStat() {
+    public void testChunkToVmMemoryStat() {
         final long TIMESTAMP = 1234l;
         final int VM_ID = 4567;
 
-        BasicDBObject dbObject = new BasicDBObject();
+        Chunk chunk = new Chunk(VmMemoryStatDAO.vmMemoryStatsCategory, false);
+
+        chunk.put(Key.TIMESTAMP, TIMESTAMP);
+        chunk.put(VmMemoryStatDAO.vmIdKey, VM_ID);
 
-        dbObject.put("timestamp", TIMESTAMP);
-        dbObject.put("vm-id", VM_ID);
-        BasicDBObject eden = new BasicDBObject();
-        eden.put("gen", "new");
-        eden.put("collector", "new-collector");
-        eden.put("used", 1l);
-        eden.put("capacity", 2l);
-        eden.put("max-capacity", 3l);
-        dbObject.put("eden", eden);
+        chunk.put(VmMemoryStatDAO.edenGenKey, "new");
+        chunk.put(VmMemoryStatDAO.edenCollectorKey, "new-collector");
+        chunk.put(VmMemoryStatDAO.edenUsedKey, 1l);
+        chunk.put(VmMemoryStatDAO.edenCapacityKey, 2l);
+        chunk.put(VmMemoryStatDAO.edenMaxCapacityKey, 3l);
 
-        BasicDBObject s0 = new BasicDBObject();
-        s0.put("gen", "new");
-        s0.put("collector", "new-collector");
-        s0.put("used", 4l);
-        s0.put("capacity", 5l);
-        s0.put("max-capacity", 6l);
-        dbObject.put("s0", s0);
+        chunk.put(VmMemoryStatDAO.s0GenKey, "new");
+        chunk.put(VmMemoryStatDAO.s0CollectorKey, "new-collector");
+        chunk.put(VmMemoryStatDAO.s0UsedKey, 4l);
+        chunk.put(VmMemoryStatDAO.s0CapacityKey, 5l);
+        chunk.put(VmMemoryStatDAO.s0MaxCapacityKey, 6l);
 
-        BasicDBObject s1 = new BasicDBObject();
-        s1.put("gen", "new");
-        s1.put("collector", "new-collector");
-        s1.put("used", 7l);
-        s1.put("capacity", 8l);
-        s1.put("max-capacity", 9l);
-        dbObject.put("s1", s1);
+        chunk.put(VmMemoryStatDAO.s1GenKey, "new");
+        chunk.put(VmMemoryStatDAO.s1CollectorKey, "new-collector");
+        chunk.put(VmMemoryStatDAO.s1UsedKey, 7l);
+        chunk.put(VmMemoryStatDAO.s1CapacityKey, 8l);
+        chunk.put(VmMemoryStatDAO.s1MaxCapacityKey, 9l);
 
-        BasicDBObject old = new BasicDBObject();
-        old.put("gen", "old");
-        old.put("collector", "old-collector");
-        old.put("used", 10l);
-        old.put("capacity", 11l);
-        old.put("max-capacity", 12l);
-        dbObject.put("old", old);
+        chunk.put(VmMemoryStatDAO.oldGenKey, "old");
+        chunk.put(VmMemoryStatDAO.oldCollectorKey, "old-collector");
+        chunk.put(VmMemoryStatDAO.oldUsedKey, 10l);
+        chunk.put(VmMemoryStatDAO.oldCapacityKey, 11l);
+        chunk.put(VmMemoryStatDAO.oldMaxCapacityKey, 12l);
 
-        BasicDBObject perm = new BasicDBObject();
-        perm.put("gen", "perm");
-        perm.put("collector", "perm-collector");
-        perm.put("used", 13l);
-        perm.put("capacity", 14l);
-        perm.put("max-capacity", 15l);
-        dbObject.put("perm", perm);
+        chunk.put(VmMemoryStatDAO.permGenKey, "perm");
+        chunk.put(VmMemoryStatDAO.permCollectorKey, "perm-collector");
+        chunk.put(VmMemoryStatDAO.permUsedKey, 13l);
+        chunk.put(VmMemoryStatDAO.permCapacityKey, 14l);
+        chunk.put(VmMemoryStatDAO.permMaxCapacityKey, 15l);
 
-        VmMemoryStat stat = new VmMemoryStatConverter().createVmMemoryStatFromDBObject(dbObject);
+        VmMemoryStat stat = new VmMemoryStatConverter().chunkToVmMemoryStat(chunk);
 
         assertNotNull(stat);
         assertEquals(TIMESTAMP, stat.getTimeStamp());
@@ -184,5 +174,4 @@
         assertEquals(1, stat.getGeneration("perm").spaces.size());
         assertEquals("perm-collector", stat.getGeneration("perm").collector);
     }
-
 }
--- a/common/src/test/java/com/redhat/thermostat/common/storage/MongoCursorTest.java	Wed Mar 28 17:44:33 2012 +0200
+++ b/common/src/test/java/com/redhat/thermostat/common/storage/MongoCursorTest.java	Wed Mar 28 11:53:44 2012 -0400
@@ -41,8 +41,11 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import org.junit.After;
 import org.junit.Before;
@@ -111,16 +114,13 @@
 
     @Test
     public void verifyCursorSort() {
-        Chunk orderBy = new Chunk(testCategory, false);
-        orderBy.put(key1, "test1");
         ArgumentCaptor<DBObject> arg = ArgumentCaptor.forClass(DBObject.class);
-        Cursor sorted = cursor.sort(orderBy);
+        Cursor sorted = cursor.sort(key1, Cursor.SortDirection.ASCENDING);
 
         verify(dbCursor).sort(arg.capture());
         DBObject orderByDBObject = arg.getValue();
         assertEquals(1, orderByDBObject.keySet().size());
-        assertEquals("test1", orderByDBObject.get("key1"));
-
+        assertEquals((Integer) Cursor.SortDirection.ASCENDING.getValue(), orderByDBObject.get(key1.getName()));
         // Verify that the sorted cursor is still return the same number of items. We leave the actual
         // sorting to Mongo and won't check it here.
         assertTrue(sorted.hasNext());