changeset 1640:9198df881601

Support getting oldest and latest POJOs Reviewed-by: omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2014-December/012314.html
author Jie Kang <jkang@redhat.com>
date Tue, 16 Dec 2014 15:34:39 -0500
parents 4bea04866e8e
children 7dc6a2862f7b
files storage/core/src/main/java/com/redhat/thermostat/storage/core/HostBoundaryPojoGetter.java storage/core/src/main/java/com/redhat/thermostat/storage/core/VmBoundaryPojoGetter.java storage/core/src/test/java/com/redhat/thermostat/storage/core/HostBoundaryPojoGetterTest.java storage/core/src/test/java/com/redhat/thermostat/storage/core/VmBoundaryPojoGetterTest.java vm-classstat/common/src/main/java/com/redhat/thermostat/vm/classstat/common/internal/VmClassStatDAOImpl.java vm-classstat/common/src/main/java/com/redhat/thermostat/vm/classstat/common/internal/VmClassStatDAOImplStatementDescriptorRegistration.java vm-cpu/common/src/main/java/com/redhat/thermostat/vm/cpu/common/internal/VmCpuStatDAOImpl.java vm-cpu/common/src/main/java/com/redhat/thermostat/vm/cpu/common/internal/VmCpuStatDAOImplStatementDescriptorRegistration.java vm-memory/common/src/main/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatDAOImpl.java vm-memory/common/src/main/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatDAOImplStatementDescriptorRegistration.java vm-memory/common/src/test/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatDAOTest.java
diffstat 11 files changed, 607 insertions(+), 146 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/HostBoundaryPojoGetter.java	Tue Dec 16 15:34:39 2014 -0500
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2012-2014 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.storage.core;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.storage.model.TimeStampedPojo;
+
+public class HostBoundaryPojoGetter<T extends TimeStampedPojo> {
+
+    // QUERY %s WHERE 'agentId' = ?s AND \
+    //                        SORT 'timeStamp' DSC  \
+    //                        LIMIT 1
+    public static final String DESC_LATEST_HOST_STAT = "QUERY %s " +
+            "WHERE '" + Key.AGENT_ID.getName() + "' = ?s " +
+            "SORT '" + Key.TIMESTAMP.getName() + "' DSC " +
+            "LIMIT 1";
+
+    // QUERY %s WHERE 'agentId' = ?s AND \
+    //                        SORT 'timeStamp' ASC  \
+    //                        LIMIT 1
+    public static final String DESC_OLDEST_HOST_STAT = "QUERY %s " +
+            "WHERE '" + Key.AGENT_ID.getName() + "' = ?s " +
+            "SORT '" + Key.TIMESTAMP.getName() + "' ASC " +
+            "LIMIT 1";
+
+    private static final Logger logger = LoggingUtils.getLogger(HostBoundaryPojoGetter.class);
+
+    private final Storage storage;
+    private final Category<T> cat;
+    private final String queryLatest;
+    private final String queryOldest;
+
+    public HostBoundaryPojoGetter(Storage storage, Category<T> cat) {
+        this.storage = storage;
+        this.cat = cat;
+        this.queryLatest = String.format(DESC_LATEST_HOST_STAT, cat.getName());
+        this.queryOldest= String.format(DESC_OLDEST_HOST_STAT, cat.getName());
+    }
+
+    public T getLatestStat(HostRef ref) {
+        return runAgentIdQuery(ref, queryLatest);
+    }
+
+    public T getOldestStat(HostRef ref) {
+        return runAgentIdQuery(ref, queryOldest);
+    }
+
+    private T runAgentIdQuery(final HostRef ref, final String descriptor) {
+        StatementDescriptor<T> desc = new StatementDescriptor<>(cat, descriptor);
+        PreparedStatement<T> prepared;
+        try {
+            prepared = storage.prepareStatement(desc);
+            prepared.setString(0, ref.getAgentId());
+            Cursor<T> cursor = prepared.executeQuery();
+            if (cursor.hasNext()) {
+                return cursor.next();
+            }
+        } catch (DescriptorParsingException e) {
+            logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e);
+        } catch (StatementExecutionException e) {
+            logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e);
+        }
+        return null;
+    }
+
+    //Package private for testing
+    String getLatestQueryDesc() {
+        return queryLatest;
+    }
+
+    String getOldestQueryDesc() {
+        return queryOldest;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/VmBoundaryPojoGetter.java	Tue Dec 16 15:34:39 2014 -0500
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2012-2014 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.storage.core;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.storage.model.TimeStampedPojo;
+
+public class VmBoundaryPojoGetter <T extends TimeStampedPojo> {
+
+    // QUERY %s WHERE 'agentId' = ?s AND \
+    //                        'vmId' = ?s \
+    //                        SORT 'timeStamp' DSC  \
+    //                        LIMIT 1
+    public static final String DESC_LATEST_VM_STAT = "QUERY %s " +
+            "WHERE '" + Key.AGENT_ID.getName() + "' = ?s " +
+            "AND '" + Key.VM_ID.getName() + "' = ?s " +
+            "SORT '" + Key.TIMESTAMP.getName() + "' DSC " +
+            "LIMIT 1";
+
+    // QUERY %s WHERE 'agentId' = ?s AND \
+    //                        'vmId' = ?s \
+    //                        SORT 'timeStamp' ASC  \
+    //                        LIMIT 1
+    public static final String DESC_OLDEST_VM_STAT = "QUERY %s " +
+            "WHERE '" + Key.AGENT_ID.getName() + "' = ?s " +
+            "AND '" + Key.VM_ID.getName() + "' = ?s " +
+            "SORT '" + Key.TIMESTAMP.getName() + "' ASC " +
+            "LIMIT 1";
+
+    private static final Logger logger = LoggingUtils.getLogger(VmBoundaryPojoGetter.class);
+
+    private final Storage storage;
+    private final Category<T> cat;
+    private final String queryLatest;
+    private final String queryOldest;
+
+    public VmBoundaryPojoGetter(Storage storage, Category<T> cat) {
+        this.storage = storage;
+        this.cat = cat;
+        this.queryLatest = String.format(DESC_LATEST_VM_STAT, cat.getName());
+        this.queryOldest = String.format(DESC_OLDEST_VM_STAT, cat.getName());
+    }
+
+    public T getLatestStat(VmRef ref) {
+        return runAgentAndVmIdQuery(ref, queryLatest);
+    }
+
+    public T getOldestStat(VmRef ref) {
+        return runAgentAndVmIdQuery(ref, queryOldest);
+    }
+
+    private T runAgentAndVmIdQuery(final VmRef ref, final String descriptor) {
+        StatementDescriptor<T> desc = new StatementDescriptor<>(cat, descriptor);
+        PreparedStatement<T> prepared;
+        try {
+            prepared = storage.prepareStatement(desc);
+            prepared.setString(0, ref.getHostRef().getAgentId());
+            prepared.setString(1, ref.getVmId());
+            Cursor<T> cursor = prepared.executeQuery();
+            if (cursor.hasNext()) {
+                return cursor.next();
+            }
+        } catch (DescriptorParsingException e) {
+            logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e);
+        } catch (StatementExecutionException e) {
+            logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e);
+        }
+        return null;
+    }
+
+    //Package private for testing
+    String getLatestQueryDesc() {
+        return queryLatest;
+    }
+
+    String getOldestQueryDesc() {
+        return queryOldest;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/core/HostBoundaryPojoGetterTest.java	Tue Dec 16 15:34:39 2014 -0500
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2012-2014 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.storage.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.model.TimeStampedPojo;
+
+public class HostBoundaryPojoGetterTest {
+    private static final String AGENT_ID = "agentid";
+    private static final String HOSTNAME = "host.example.com";
+    private static final String CATEGORY_NAME = "host-boundary-category";
+    // 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<TestPojo> cat =  new Category<>(CATEGORY_NAME, TestPojo.class);
+
+    private static long t1 = 1;
+    private static long t2 = 5;
+
+    private static long lc1 = 10;
+    private static long lc2 = 20;
+
+    private HostRef hostRef;
+    private TestPojo result1, result2;
+
+    @Before
+    public void setUp() {
+        hostRef = new HostRef(AGENT_ID, HOSTNAME);
+        result1 = mock(TestPojo.class);
+        when(result1.getTimeStamp()).thenReturn(t1);
+        when(result1.getData()).thenReturn(lc1);
+        result2 = mock(TestPojo.class);
+        when(result2.getTimeStamp()).thenReturn(t2);
+        when(result2.getData()).thenReturn(lc2);
+    }
+
+    @Test
+    public void verifyLatestQueryDescriptorFormat() {
+        String latestExpected = "QUERY %s WHERE 'agentId' = ?s SORT 'timeStamp' DSC LIMIT 1";
+        assertEquals(latestExpected, HostBoundaryPojoGetter.DESC_LATEST_HOST_STAT);
+    }
+
+    @Test
+    public void verifyOldestQueryDescriptorFormat() {
+        String oldestExpected = "QUERY %s WHERE 'agentId' = ?s SORT 'timeStamp' ASC LIMIT 1";
+        assertEquals(oldestExpected, HostBoundaryPojoGetter.DESC_OLDEST_HOST_STAT);
+    }
+
+    @Test
+    public void verifyLatestQueryDescriptorIsSane() {
+        Storage storage = mock(Storage.class);
+        HostBoundaryPojoGetter<TestPojo> getter = new HostBoundaryPojoGetter<>(storage, cat);
+
+        String actualLatestDesc = getter.getLatestQueryDesc();
+        String latestExpected = "QUERY host-boundary-category WHERE 'agentId' = ?s SORT 'timeStamp' DSC LIMIT 1";
+        assertEquals(latestExpected, actualLatestDesc);
+    }
+
+    @Test
+    public void verifyOldestQueryDescriptorIsSane() {
+        Storage storage = mock(Storage.class);
+        HostBoundaryPojoGetter<TestPojo> getter = new HostBoundaryPojoGetter<>(storage, cat);
+
+        String actualOldestDesc = getter.getOldestQueryDesc();
+        String oldestExpected = "QUERY host-boundary-category WHERE 'agentId' = ?s SORT 'timeStamp' ASC LIMIT 1";
+
+        assertEquals(oldestExpected, actualOldestDesc);
+    }
+
+    @Test
+    public void testGetOldest() throws DescriptorParsingException, StatementExecutionException {
+        Cursor<TestPojo> cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(result1).thenReturn(null);
+
+        PreparedStatement<TestPojo> query = (PreparedStatement<TestPojo>) mock(PreparedStatement.class);
+        when(query.executeQuery()).thenReturn(cursor);
+
+        Storage storage = mock(Storage.class);
+        when(storage.prepareStatement(anyDescriptor())).thenReturn(query);
+
+        HostBoundaryPojoGetter<TestPojo> getter = new HostBoundaryPojoGetter<>(storage, cat);
+
+        TestPojo oldest = getter.getOldestStat(hostRef);
+
+        assertEquals(t1, oldest.getTimeStamp());
+        assertEquals(lc1, oldest.getData());
+    }
+
+    @Test
+    public void testGetLatest() throws DescriptorParsingException, StatementExecutionException {
+        Cursor<TestPojo> cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(result2).thenReturn(null);
+
+        PreparedStatement<TestPojo> query = (PreparedStatement<TestPojo>) mock(PreparedStatement.class);
+        when(query.executeQuery()).thenReturn(cursor);
+
+        Storage storage = mock(Storage.class);
+        when(storage.prepareStatement(anyDescriptor())).thenReturn(query);
+
+        HostBoundaryPojoGetter<TestPojo> getter = new HostBoundaryPojoGetter<>(storage, cat);
+
+        TestPojo oldest = getter.getLatestStat(hostRef);
+
+        assertEquals(t2, oldest.getTimeStamp());
+        assertEquals(lc2, oldest.getData());
+    }
+
+    @SuppressWarnings("unchecked")
+    private StatementDescriptor<TestPojo> anyDescriptor() {
+        return (StatementDescriptor<TestPojo>) any(StatementDescriptor.class);
+    }
+
+    private static interface TestPojo extends TimeStampedPojo {
+        long getData();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/core/VmBoundaryPojoGetterTest.java	Tue Dec 16 15:34:39 2014 -0500
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2012-2014 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.storage.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.model.TimeStampedPojo;
+
+public class VmBoundaryPojoGetterTest {
+    private static final String AGENT_ID = "agentid";
+    private static final String HOSTNAME = "host.example.com";
+    private static final String VM_ID = "vmId";
+    private static final int VM_PID = 123;
+    private static final String MAIN_CLASS = "Foo.class";
+    private static final String CATEGORY_NAME = "vm-boundary-category";
+    // 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<TestPojo> cat =  new Category<>(CATEGORY_NAME, TestPojo.class);
+
+    private static long t1 = 1;
+    private static long t2 = 5;
+
+    private static long lc1 = 10;
+    private static long lc2 = 20;
+
+    private HostRef hostRef;
+    private VmRef vmRef;
+    private TestPojo result1, result2;
+
+    @Before
+    public void setUp() {
+        hostRef = new HostRef(AGENT_ID, HOSTNAME);
+        vmRef = new VmRef(hostRef, VM_ID, VM_PID, MAIN_CLASS);
+        result1 = mock(TestPojo.class);
+        when(result1.getTimeStamp()).thenReturn(t1);
+        when(result1.getData()).thenReturn(lc1);
+        result2 = mock(TestPojo.class);
+        when(result2.getTimeStamp()).thenReturn(t2);
+        when(result2.getData()).thenReturn(lc2);
+    }
+
+    @Test
+    public void verifyLatestQueryDescriptorFormat() {
+        String latestExpected = "QUERY %s WHERE 'agentId' = ?s AND " +
+                "'vmId' = ?s SORT 'timeStamp' DSC LIMIT 1";
+        assertEquals(latestExpected, VmBoundaryPojoGetter.DESC_LATEST_VM_STAT);
+    }
+
+    @Test
+    public void verifyOldestQueryDescriptorFormat() {
+        String oldestExpected = "QUERY %s WHERE 'agentId' = ?s AND " +
+                "'vmId' = ?s SORT 'timeStamp' ASC LIMIT 1";
+        assertEquals(oldestExpected, VmBoundaryPojoGetter.DESC_OLDEST_VM_STAT);
+    }
+
+    @Test
+    public void verifyLatestQueryDescriptorIsSane() {
+        Storage storage = mock(Storage.class);
+        VmBoundaryPojoGetter<TestPojo> getter = new VmBoundaryPojoGetter<>(storage, cat);
+
+        String actualLatestDesc = getter.getLatestQueryDesc();
+        String latestExpected = "QUERY vm-boundary-category WHERE 'agentId' = ?s AND " +
+                "'vmId' = ?s SORT 'timeStamp' DSC LIMIT 1";
+        assertEquals(latestExpected, actualLatestDesc);
+    }
+
+    @Test
+    public void verifyOldestQueryDescriptorIsSane() {
+        Storage storage = mock(Storage.class);
+        VmBoundaryPojoGetter<TestPojo> getter = new VmBoundaryPojoGetter<>(storage, cat);
+
+        String actualOldestDesc = getter.getOldestQueryDesc();
+        String oldestExpected = "QUERY vm-boundary-category WHERE 'agentId' = ?s AND " +
+                "'vmId' = ?s SORT 'timeStamp' ASC LIMIT 1";
+
+        assertEquals(oldestExpected, actualOldestDesc);
+    }
+
+    @Test
+         public void testGetOldest() throws DescriptorParsingException, StatementExecutionException {
+        Cursor<TestPojo> cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(result1).thenReturn(null);
+
+        PreparedStatement<TestPojo> query = (PreparedStatement<TestPojo>) mock(PreparedStatement.class);
+        when(query.executeQuery()).thenReturn(cursor);
+
+        Storage storage = mock(Storage.class);
+        when(storage.prepareStatement(anyDescriptor())).thenReturn(query);
+
+        VmBoundaryPojoGetter<TestPojo> getter = new VmBoundaryPojoGetter<>(storage, cat);
+
+        TestPojo oldest = getter.getOldestStat(vmRef);
+
+        assertEquals(t1, oldest.getTimeStamp());
+        assertEquals(lc1, oldest.getData());
+    }
+
+    @Test
+    public void testGetLatest() throws DescriptorParsingException, StatementExecutionException {
+        Cursor<TestPojo> cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(result2).thenReturn(null);
+
+        PreparedStatement<TestPojo> query = (PreparedStatement<TestPojo>) mock(PreparedStatement.class);
+        when(query.executeQuery()).thenReturn(cursor);
+
+        Storage storage = mock(Storage.class);
+        when(storage.prepareStatement(anyDescriptor())).thenReturn(query);
+
+        VmBoundaryPojoGetter<TestPojo> getter = new VmBoundaryPojoGetter<>(storage, cat);
+
+        TestPojo oldest = getter.getLatestStat(vmRef);
+
+        assertEquals(t2, oldest.getTimeStamp());
+        assertEquals(lc2, oldest.getData());
+    }
+
+    @SuppressWarnings("unchecked")
+    private StatementDescriptor<TestPojo> anyDescriptor() {
+        return (StatementDescriptor<TestPojo>) any(StatementDescriptor.class);
+    }
+
+    private static interface TestPojo extends TimeStampedPojo {
+        long getData();
+    }
+}
--- a/vm-classstat/common/src/main/java/com/redhat/thermostat/vm/classstat/common/internal/VmClassStatDAOImpl.java	Tue Dec 16 12:01:20 2014 -0500
+++ b/vm-classstat/common/src/main/java/com/redhat/thermostat/vm/classstat/common/internal/VmClassStatDAOImpl.java	Tue Dec 16 15:34:39 2014 -0500
@@ -48,6 +48,7 @@
 import com.redhat.thermostat.storage.core.StatementDescriptor;
 import com.redhat.thermostat.storage.core.StatementExecutionException;
 import com.redhat.thermostat.storage.core.Storage;
+import com.redhat.thermostat.storage.core.VmBoundaryPojoGetter;
 import com.redhat.thermostat.storage.core.VmLatestPojoListGetter;
 import com.redhat.thermostat.storage.core.VmRef;
 import com.redhat.thermostat.storage.core.VmTimeIntervalPojoListGetter;
@@ -67,45 +68,27 @@
                  "'" + Key.TIMESTAMP.getName() + "' = ?l , " +
                  "'" + loadedClassesKey.getName() + "' = ?l";
 
-    // LATEST vm-cpu-stats WHERE 'agentId' = ?s AND \
-    //                        'vmId' = ?s \
-    //                        SORT 'timeStamp' ASC  \
-    //                        LIMIT 1
-    static final String DESC_OLDEST_VM_CLASS_STAT = "QUERY " + vmClassStatsCategory.getName() +
-            " WHERE '" + Key.AGENT_ID.getName() + "' = ?s " +
-            "   AND '" + Key.VM_ID.getName() + "' = ?s " +
-            "  SORT '" + Key.TIMESTAMP.getName() + "' ASC " +
-            "  LIMIT 1";
-
-    // LATEST vm-cpu-stats WHERE 'agentId' = ?s AND \
-    //                        'vmId' = ?s \
-    //                        SORT 'timeStamp' DSC  \
-    //                        LIMIT 1
-    static final String DESC_LATEST_VM_CLASS_STAT = "QUERY " + vmClassStatsCategory.getName() +
-            " WHERE '" + Key.AGENT_ID.getName() + "' = ?s " +
-            "   AND '" + Key.VM_ID.getName() + "' = ?s " +
-            "  SORT '" + Key.TIMESTAMP.getName() + "' DSC " +
-            "  LIMIT 1";
-
     private final Storage storage;
-    private final VmLatestPojoListGetter<VmClassStat> getter;
-    private final VmTimeIntervalPojoListGetter<VmClassStat> otherGetter;
+    private final VmLatestPojoListGetter<VmClassStat> latestGetter;
+    private final VmTimeIntervalPojoListGetter<VmClassStat> intervalGetter;
+    private final VmBoundaryPojoGetter<VmClassStat> boundaryGetter;
 
     VmClassStatDAOImpl(Storage storage) {
         this.storage = storage;
         storage.registerCategory(vmClassStatsCategory);
-        this.getter = new VmLatestPojoListGetter<>(storage, vmClassStatsCategory);
-        this.otherGetter = new VmTimeIntervalPojoListGetter<>(storage, vmClassStatsCategory);
+        this.latestGetter = new VmLatestPojoListGetter<>(storage, vmClassStatsCategory);
+        this.intervalGetter = new VmTimeIntervalPojoListGetter<>(storage, vmClassStatsCategory);
+        this.boundaryGetter = new VmBoundaryPojoGetter<>(storage, vmClassStatsCategory);
     }
 
     @Override
     public List<VmClassStat> getLatestClassStats(VmRef ref, long lastUpdateTime) {
-        return getter.getLatest(ref, lastUpdateTime);
+        return latestGetter.getLatest(ref, lastUpdateTime);
     }
 
     @Override
     public List<VmClassStat> getClassStats(VmRef ref, long since, long to) {
-        return otherGetter.getLatest(ref, since, to);
+        return intervalGetter.getLatest(ref, since, to);
     }
 
     @Override
@@ -128,31 +111,13 @@
 
     @Override
     public VmClassStat getOldest(final VmRef ref) {
-        return runAgentAndVmIdQuery(ref, DESC_OLDEST_VM_CLASS_STAT);
+        return boundaryGetter.getOldestStat(ref);
     }
 
     @Override
     public VmClassStat getLatest(final VmRef ref) {
-        return runAgentAndVmIdQuery(ref, DESC_LATEST_VM_CLASS_STAT);
+        return boundaryGetter.getLatestStat(ref);
     }
 
-    private VmClassStat runAgentAndVmIdQuery(final VmRef ref, final String descriptor) {
-        StatementDescriptor<VmClassStat> desc = new StatementDescriptor<>(vmClassStatsCategory, descriptor);
-        PreparedStatement<VmClassStat> prepared;
-        try {
-            prepared = storage.prepareStatement(desc);
-            prepared.setString(0, ref.getHostRef().getAgentId());
-            prepared.setString(1, ref.getVmId());
-            Cursor<VmClassStat> cursor = prepared.executeQuery();
-            if (cursor.hasNext()) {
-                return cursor.next();
-            }
-        } catch (DescriptorParsingException e) {
-            logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e);
-        } catch (StatementExecutionException e) {
-            logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e);
-        }
-        return null;
-    }
 }
 
--- a/vm-classstat/common/src/main/java/com/redhat/thermostat/vm/classstat/common/internal/VmClassStatDAOImplStatementDescriptorRegistration.java	Tue Dec 16 12:01:20 2014 -0500
+++ b/vm-classstat/common/src/main/java/com/redhat/thermostat/vm/classstat/common/internal/VmClassStatDAOImplStatementDescriptorRegistration.java	Tue Dec 16 15:34:39 2014 -0500
@@ -40,6 +40,7 @@
 import java.util.Set;
 
 import com.redhat.thermostat.storage.core.PreparedParameter;
+import com.redhat.thermostat.storage.core.VmBoundaryPojoGetter;
 import com.redhat.thermostat.storage.core.VmLatestPojoListGetter;
 import com.redhat.thermostat.storage.core.VmTimeIntervalPojoListGetter;
 import com.redhat.thermostat.storage.core.auth.DescriptorMetadata;
@@ -58,14 +59,18 @@
             VmClassStatDAO.vmClassStatsCategory.getName());
     static final String RANGE = String.format(VmTimeIntervalPojoListGetter.VM_INTERVAL_QUERY_FORMAT,
             VmClassStatDAO.vmClassStatsCategory.getName());
+    static final String LATEST_STAT = String.format(VmBoundaryPojoGetter.DESC_LATEST_VM_STAT,
+            VmClassStatDAO.vmClassStatsCategory.getName());
+    static final String OLDEST_STAT = String.format(VmBoundaryPojoGetter.DESC_OLDEST_VM_STAT,
+            VmClassStatDAO.vmClassStatsCategory.getName());
 
     @Override
     public Set<String> getStatementDescriptors() {
         Set<String> descs = new HashSet<>(1);
         descs.add(LATEST);
         descs.add(RANGE);
-        descs.add(VmClassStatDAOImpl.DESC_LATEST_VM_CLASS_STAT);
-        descs.add(VmClassStatDAOImpl.DESC_OLDEST_VM_CLASS_STAT);
+        descs.add(LATEST_STAT);
+        descs.add(OLDEST_STAT);
         descs.add(VmClassStatDAOImpl.DESC_ADD_VM_CLASS_STAT);
         return descs;
     }
--- a/vm-cpu/common/src/main/java/com/redhat/thermostat/vm/cpu/common/internal/VmCpuStatDAOImpl.java	Tue Dec 16 12:01:20 2014 -0500
+++ b/vm-cpu/common/src/main/java/com/redhat/thermostat/vm/cpu/common/internal/VmCpuStatDAOImpl.java	Tue Dec 16 15:34:39 2014 -0500
@@ -48,6 +48,7 @@
 import com.redhat.thermostat.storage.core.StatementDescriptor;
 import com.redhat.thermostat.storage.core.StatementExecutionException;
 import com.redhat.thermostat.storage.core.Storage;
+import com.redhat.thermostat.storage.core.VmBoundaryPojoGetter;
 import com.redhat.thermostat.storage.core.VmLatestPojoListGetter;
 import com.redhat.thermostat.storage.core.VmRef;
 import com.redhat.thermostat.storage.core.VmTimeIntervalPojoListGetter;
@@ -67,74 +68,37 @@
                  "'" + Key.TIMESTAMP.getName() + "' = ?l , " +
                  "'" + vmCpuLoadKey.getName() + "' = ?d";
 
-    // QUERY vm-cpu-stats WHERE 'agentId' = ?s AND \
-    //                        'vmId' = ?s \
-    //                        SORT 'timeStamp' ASC  \
-    //                        LIMIT 1
-    static final String DESC_OLDEST_VM_CPU_STAT = "QUERY " + vmCpuStatCategory.getName() +
-            " WHERE '" + Key.AGENT_ID.getName() + "' = ?s " +
-            "   AND '" + Key.VM_ID.getName() + "' = ?s " +
-            "  SORT '" + Key.TIMESTAMP.getName() + "' ASC " +
-            "  LIMIT 1";
-
-    // QUERY vm-cpu-stats WHERE 'agentId' = ?s AND \
-    //                        'vmId' = ?s \
-    //                        SORT 'timeStamp' DSC  \
-    //                        LIMIT 1
-    static final String DESC_LATEST_VM_CPU_STAT = "QUERY " + vmCpuStatCategory.getName() +
-            " WHERE '" + Key.AGENT_ID.getName() + "' = ?s " +
-            "   AND '" + Key.VM_ID.getName() + "' = ?s " +
-            "  SORT '" + Key.TIMESTAMP.getName() + "' DSC " +
-            "  LIMIT 1";
-
     private final Storage storage;
-    private final VmLatestPojoListGetter<VmCpuStat> getter;
-    private final VmTimeIntervalPojoListGetter<VmCpuStat> otherGetter;
+    private final VmLatestPojoListGetter<VmCpuStat> latestGetter;
+    private final VmTimeIntervalPojoListGetter<VmCpuStat> intervalGetter;
+    private final VmBoundaryPojoGetter<VmCpuStat> boundaryGetter;
 
     VmCpuStatDAOImpl(Storage storage) {
         this.storage = storage;
         storage.registerCategory(vmCpuStatCategory);
-        this.getter = new VmLatestPojoListGetter<>(storage, vmCpuStatCategory);
-        this.otherGetter = new VmTimeIntervalPojoListGetter<>(storage, vmCpuStatCategory);
+        this.latestGetter = new VmLatestPojoListGetter<>(storage, vmCpuStatCategory);
+        this.intervalGetter = new VmTimeIntervalPojoListGetter<>(storage, vmCpuStatCategory);
+        this.boundaryGetter = new VmBoundaryPojoGetter<>(storage, vmCpuStatCategory);
     }
 
     @Override
     public List<VmCpuStat> getLatestVmCpuStats(VmRef ref, long since) {
-        return getter.getLatest(ref, since);
+        return latestGetter.getLatest(ref, since);
     }
 
     @Override
     public List<VmCpuStat> getVmCpuStats(VmRef ref, long since, long to) {
-        return otherGetter.getLatest(ref, since, to);
+        return intervalGetter.getLatest(ref, since, to);
     }
 
     @Override
     public VmCpuStat getLatest(VmRef ref) {
-        return runAgentAndVmIdQuery(ref, DESC_LATEST_VM_CPU_STAT);
+        return boundaryGetter.getLatestStat(ref);
     }
 
     @Override
     public VmCpuStat getOldest(VmRef ref) {
-        return runAgentAndVmIdQuery(ref, DESC_OLDEST_VM_CPU_STAT);
-    }
-
-    private VmCpuStat runAgentAndVmIdQuery(VmRef ref, String descriptor) {
-        StatementDescriptor<VmCpuStat> desc = new StatementDescriptor<>(vmCpuStatCategory, descriptor);
-        PreparedStatement<VmCpuStat> prepared;
-        try {
-            prepared = storage.prepareStatement(desc);
-            prepared.setString(0, ref.getHostRef().getAgentId());
-            prepared.setString(1, ref.getVmId());
-            Cursor<VmCpuStat> cursor = prepared.executeQuery();
-            if (cursor.hasNext()) {
-                return cursor.next();
-            }
-        } catch (DescriptorParsingException e) {
-            logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e);
-        } catch (StatementExecutionException e) {
-            logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e);
-        }
-        return null;
+        return boundaryGetter.getOldestStat(ref);
     }
 
     @Override
--- a/vm-cpu/common/src/main/java/com/redhat/thermostat/vm/cpu/common/internal/VmCpuStatDAOImplStatementDescriptorRegistration.java	Tue Dec 16 12:01:20 2014 -0500
+++ b/vm-cpu/common/src/main/java/com/redhat/thermostat/vm/cpu/common/internal/VmCpuStatDAOImplStatementDescriptorRegistration.java	Tue Dec 16 15:34:39 2014 -0500
@@ -40,6 +40,7 @@
 import java.util.Set;
 
 import com.redhat.thermostat.storage.core.PreparedParameter;
+import com.redhat.thermostat.storage.core.VmBoundaryPojoGetter;
 import com.redhat.thermostat.storage.core.VmLatestPojoListGetter;
 import com.redhat.thermostat.storage.core.VmTimeIntervalPojoListGetter;
 import com.redhat.thermostat.storage.core.auth.DescriptorMetadata;
@@ -58,13 +59,18 @@
             VmCpuStatDAO.vmCpuStatCategory.getName());
     static final String rangeDescriptor = String.format(VmTimeIntervalPojoListGetter.VM_INTERVAL_QUERY_FORMAT,
             VmCpuStatDAO.vmCpuStatCategory.getName());
+    static final String latestStatDescriptor = String.format(VmBoundaryPojoGetter.DESC_LATEST_VM_STAT,
+            VmCpuStatDAO.vmCpuStatCategory.getName());
+    static final String oldestStatDescriptor = String.format(VmBoundaryPojoGetter.DESC_OLDEST_VM_STAT,
+            VmCpuStatDAO.vmCpuStatCategory.getName());
+
 
     @Override
     public Set<String> getStatementDescriptors() {
         Set<String> descs = new HashSet<>();
         descs.add(VmCpuStatDAOImpl.DESC_ADD_VM_CPU_STAT);
-        descs.add(VmCpuStatDAOImpl.DESC_LATEST_VM_CPU_STAT);
-        descs.add(VmCpuStatDAOImpl.DESC_OLDEST_VM_CPU_STAT);
+        descs.add(latestStatDescriptor);
+        descs.add(oldestStatDescriptor);
         descs.add(latestDescriptor);
         descs.add(rangeDescriptor);
         return descs;
--- a/vm-memory/common/src/main/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatDAOImpl.java	Tue Dec 16 12:01:20 2014 -0500
+++ b/vm-memory/common/src/main/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatDAOImpl.java	Tue Dec 16 15:34:39 2014 -0500
@@ -48,6 +48,7 @@
 import com.redhat.thermostat.storage.core.StatementDescriptor;
 import com.redhat.thermostat.storage.core.StatementExecutionException;
 import com.redhat.thermostat.storage.core.Storage;
+import com.redhat.thermostat.storage.core.VmBoundaryPojoGetter;
 import com.redhat.thermostat.storage.core.VmLatestPojoListGetter;
 import com.redhat.thermostat.storage.core.VmRef;
 import com.redhat.thermostat.storage.core.VmTimeIntervalPojoListGetter;
@@ -57,25 +58,7 @@
 class VmMemoryStatDAOImpl implements VmMemoryStatDAO {
 
     private static final Logger logger = LoggingUtils.getLogger(VmMemoryStatDAOImpl.class);
-    // QUERY vm-cpu-stats WHERE 'agentId' = ?s AND \
-    //                        'vmId' = ?s \
-    //                        SORT 'timeStamp' ASC  \
-    //                        LIMIT 1
-    static final String DESC_OLDEST_VM_MEMORY_STAT = "QUERY " + vmMemoryStatsCategory.getName() + " " +
-            "WHERE '" + Key.AGENT_ID.getName() + "' = ?s " +
-            "AND '" + Key.VM_ID.getName() + "' = ?s " +
-            "SORT '" + Key.TIMESTAMP.getName() + "' ASC " +
-            "LIMIT 1";
 
-    // QUERY vm-cpu-stats WHERE 'agentId' = ?s AND \
-    //                        'vmId' = ?s \
-    //                        SORT 'timeStamp' DSC  \
-    //                        LIMIT 1
-    static final String DESC_LATEST_VM_MEMORY_STAT = "QUERY " + vmMemoryStatsCategory.getName() + " " +
-            "WHERE '" + Key.AGENT_ID.getName() + "' = ?s " +
-            "AND '" + Key.VM_ID.getName() + "' = ?s " +
-            "SORT '" + Key.TIMESTAMP.getName() + "' DSC " +
-            "LIMIT 1";
     // ADD vm-memory-stats SET 'agentId' = ?s , \
     //                         'vmId' = ?s , \
     //                         'timeStamp' = ?s , \
@@ -87,43 +70,26 @@
                  "'" + generationsKey.getName() + "' = ?p[";
     
     private final Storage storage;
-    private final VmLatestPojoListGetter<VmMemoryStat> getter;
-    private final VmTimeIntervalPojoListGetter<VmMemoryStat> otherGetter;
+    private final VmLatestPojoListGetter<VmMemoryStat> latestGetter;
+    private final VmTimeIntervalPojoListGetter<VmMemoryStat> intervalGetter;
+    private final VmBoundaryPojoGetter<VmMemoryStat> boundaryGetter;
 
     VmMemoryStatDAOImpl(Storage storage) {
         this.storage = storage;
         storage.registerCategory(vmMemoryStatsCategory);
-        getter = new VmLatestPojoListGetter<>(storage, vmMemoryStatsCategory);
-        otherGetter = new VmTimeIntervalPojoListGetter<>(storage, vmMemoryStatsCategory);
+        latestGetter = new VmLatestPojoListGetter<>(storage, vmMemoryStatsCategory);
+        intervalGetter = new VmTimeIntervalPojoListGetter<>(storage, vmMemoryStatsCategory);
+        boundaryGetter = new VmBoundaryPojoGetter<>(storage, vmMemoryStatsCategory);
     }
 
     @Override
     public VmMemoryStat getLatestMemoryStat(VmRef ref) {
-        return runAgentAndVmIdQuery(ref, DESC_LATEST_VM_MEMORY_STAT);
+        return boundaryGetter.getLatestStat(ref);
     }
 
     @Override
     public VmMemoryStat getOldestMemoryStat(VmRef ref) {
-        return runAgentAndVmIdQuery(ref, DESC_OLDEST_VM_MEMORY_STAT);
-    }
-
-    private VmMemoryStat runAgentAndVmIdQuery(VmRef ref, String descriptor) {
-        StatementDescriptor<VmMemoryStat> desc = new StatementDescriptor<>(vmMemoryStatsCategory, descriptor);
-        PreparedStatement<VmMemoryStat> prepared;
-        try {
-            prepared = storage.prepareStatement(desc);
-            prepared.setString(0, ref.getHostRef().getAgentId());
-            prepared.setString(1, ref.getVmId());
-            Cursor<VmMemoryStat> cursor = prepared.executeQuery();
-            if (cursor.hasNext()) {
-                return cursor.next();
-            }
-        } catch (DescriptorParsingException e) {
-            logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e);
-        } catch (StatementExecutionException e) {
-            logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e);
-        }
-        return null;
+        return boundaryGetter.getOldestStat(ref);
     }
 
     @Override
@@ -146,12 +112,12 @@
 
     @Override
     public List<VmMemoryStat> getLatestVmMemoryStats(VmRef ref, long since) {
-        return getter.getLatest(ref, since);
+        return latestGetter.getLatest(ref, since);
     }
 
     @Override
     public List<VmMemoryStat> getVmMemoryStats(VmRef ref, long since, long to) {
-        return otherGetter.getLatest(ref, since, to);
+        return intervalGetter.getLatest(ref, since, to);
     }
 }
 
--- a/vm-memory/common/src/main/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatDAOImplStatementDescriptorRegistration.java	Tue Dec 16 12:01:20 2014 -0500
+++ b/vm-memory/common/src/main/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatDAOImplStatementDescriptorRegistration.java	Tue Dec 16 15:34:39 2014 -0500
@@ -40,6 +40,7 @@
 import java.util.Set;
 
 import com.redhat.thermostat.storage.core.PreparedParameter;
+import com.redhat.thermostat.storage.core.VmBoundaryPojoGetter;
 import com.redhat.thermostat.storage.core.VmLatestPojoListGetter;
 import com.redhat.thermostat.storage.core.VmTimeIntervalPojoListGetter;
 import com.redhat.thermostat.storage.core.auth.DescriptorMetadata;
@@ -58,12 +59,16 @@
             VmMemoryStatDAO.vmMemoryStatsCategory.getName());
     static final String rangeDescriptor = String.format(VmTimeIntervalPojoListGetter.VM_INTERVAL_QUERY_FORMAT,
             VmMemoryStatDAO.vmMemoryStatsCategory.getName());
+    static final String latestStatDescriptor = String.format(VmBoundaryPojoGetter.DESC_LATEST_VM_STAT,
+            VmMemoryStatDAO.vmMemoryStatsCategory.getName());
+    static final String oldestStatDescriptor = String.format(VmBoundaryPojoGetter.DESC_OLDEST_VM_STAT,
+            VmMemoryStatDAO.vmMemoryStatsCategory.getName());
     
     @Override
     public Set<String> getStatementDescriptors() {
         Set<String> descs = new HashSet<>(5);
-        descs.add(VmMemoryStatDAOImpl.DESC_LATEST_VM_MEMORY_STAT);
-        descs.add(VmMemoryStatDAOImpl.DESC_OLDEST_VM_MEMORY_STAT);
+        descs.add(latestStatDescriptor);
+        descs.add(oldestStatDescriptor);
         descs.add(VmMemoryStatDAOImpl.DESC_ADD_VM_MEMORY_STAT);
 
         descs.add(latestDescriptor);
--- a/vm-memory/common/src/test/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatDAOTest.java	Tue Dec 16 12:01:20 2014 -0500
+++ b/vm-memory/common/src/test/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatDAOTest.java	Tue Dec 16 15:34:39 2014 -0500
@@ -114,8 +114,6 @@
     
     @Test
     public void preparedQueryDescriptorsAreSane() {
-        String expectedQueryThreadCaps = "QUERY vm-memory-stats WHERE 'agentId' = ?s AND 'vmId' = ?s SORT 'timeStamp' DSC LIMIT 1";
-        assertEquals(expectedQueryThreadCaps, VmMemoryStatDAOImpl.DESC_LATEST_VM_MEMORY_STAT);
         String addVmMemoryStat = "ADD vm-memory-stats SET 'agentId' = ?s , " +
                                         "'vmId' = ?s , " +
                                         "'timeStamp' = ?l , " +