changeset 1331:f0eb836ff306

Add support for indexing keys Reviewed-by: jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-November/008725.html
author Omair Majid <omajid@redhat.com>
date Mon, 18 Nov 2013 14:15:56 -0500
parents 5f64da4d382c
children 2130033fd660
files storage/core/src/main/java/com/redhat/thermostat/storage/core/Category.java storage/core/src/main/java/com/redhat/thermostat/storage/internal/AdaptedCategory.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java thread/collector/src/main/java/com/redhat/thermostat/thread/dao/ThreadDao.java web/common/src/test/java/com/redhat/thermostat/web/common/CategorySerializationTest.java
diffstat 5 files changed, 87 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/Category.java	Fri Nov 15 11:14:29 2013 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/Category.java	Mon Nov 18 14:15:56 2013 -0500
@@ -36,9 +36,11 @@
 
 package com.redhat.thermostat.storage.core;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -69,6 +71,17 @@
      * This key map gets serialized via JSON.
      */
     protected Map<String, Key<?>> keys;
+
+    /*
+     * A de-facto unmodifiable list of keys to be indexed. All of these keys
+     * should be indexed by the storage (so sorting by this should be possible).
+     * Set via the constructor. Exceptions are AdaptedCategory and JSON
+     * serialization.
+     *
+     * This list gets serialized via JSON.
+     */
+    protected List<Key<?>> indexedKeys;
+
     /*
      * A de-facto immutable field, set via setDataClass() called by the
      * constructor. If null dataClassName must be set. This is to make Category
@@ -98,17 +111,43 @@
      * 
      * @param name
      *            the name of the category
+     * @param dataClass
+     *            the Class object representing the data
+     * @param keys
+     *            an array of Key object which represent the data for this category
      * 
      * @throws IllegalArgumentException
      *             if a Category is created with a name that has been used
      *             before
      */
     public Category(String name, Class<T> dataClass, Key<?>... keys) {
+    	this(name, dataClass, Arrays.asList(keys), Collections.<Key<?>>emptyList());
+    }
+
+    /**
+     * Creates a new Category instance with the specified name.
+     *
+     * @param name
+     *            the name of the category
+     * @param dataClass
+     *            the Class object representing the data
+     * @param indexedKeys
+     *            the keys that will be used for sorting and should be indexed
+     *            (or otherwise optimized) by the storage
+     * @param keys
+     *            an array of Key object which represent the data for this category
+     *
+     * @throws IllegalArgumentException
+     *             if a Category is created with a name that has been used
+     *             before
+     */
+    public Category(String name, Class<T> dataClass, List<Key<?>> keys, List<Key<?>> indexedKeys) {
         Map<String, Key<?>> keysMap = new HashMap<String, Key<?>>();
         for (Key<?> key : keys) {
             keysMap.put(key.getName(), key);
         }
         this.keys = Collections.unmodifiableMap(keysMap);
+        this.indexedKeys = Collections.unmodifiableList(indexedKeys);
         setName(name);
         setDataClass(dataClass);
     }
@@ -182,6 +221,10 @@
         return keys.get(name);
     }
 
+    public List<Key<?>> getIndexedKeys() {
+    	return indexedKeys;
+    }
+
     @Override
     public String toString() {
         return getName() + "|" + getDataClass().getName() + "|" + keys;
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/AdaptedCategory.java	Fri Nov 15 11:14:29 2013 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/AdaptedCategory.java	Mon Nov 18 14:15:56 2013 -0500
@@ -71,6 +71,7 @@
             String msg = "Can only adapt to aggregate results!";
             throw new IllegalArgumentException(msg);
         }
+        this.indexedKeys = Collections.unmodifiableList(category.getIndexedKeys());
         this.dataClassName = dataClass.getName();
     }
     
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java	Fri Nov 15 11:14:29 2013 -0500
+++ b/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java	Mon Nov 18 14:15:56 2013 -0500
@@ -451,6 +451,9 @@
             DBCollection coll;
             if (! db.collectionExists(name)) {
                 coll = db.createCollection(name, new BasicDBObject("capped", false));
+                for (Key<?> key: category.getIndexedKeys()) {
+                    coll.ensureIndex(key.getName());
+                }
             } else {
                 coll = db.getCollection(name);
             }
--- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/ThreadDao.java	Fri Nov 15 11:14:29 2013 -0500
+++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/ThreadDao.java	Mon Nov 18 14:15:56 2013 -0500
@@ -36,6 +36,7 @@
 
 package com.redhat.thermostat.thread.dao;
 
+import java.util.Arrays;
 import java.util.List;
 
 import com.redhat.thermostat.common.model.Range;
@@ -98,13 +99,20 @@
     static final Key<Long> THREAD_BLOCKED_COUNT_KEY = new Key<Long>("threadBlockedCount");
     static final Key<Long> THREAD_WAIT_COUNT_KEY = new Key<Long>("threadWaitCount");
     static final Category<ThreadInfoData> THREAD_INFO =
-            new Category<>("vm-thread-info", ThreadInfoData.class, Key.AGENT_ID, Key.VM_ID,
-                         Key.TIMESTAMP, THREAD_NAME_KEY, THREAD_ID_KEY,
-                         THREAD_STATE_KEY,
-                         THREAD_CPU_TIME_KEY,
-                         THREAD_ALLOCATED_BYTES_KEY,
-                         THREAD_USER_TIME_KEY, THREAD_BLOCKED_COUNT_KEY,
-                         THREAD_WAIT_COUNT_KEY);
+            new Category<>("vm-thread-info", ThreadInfoData.class,
+                         Arrays.<Key<?>>asList(
+                                 Key.AGENT_ID,
+                                 Key.VM_ID,
+                                 Key.TIMESTAMP,
+                                 THREAD_NAME_KEY,
+                                 THREAD_ID_KEY,
+                                 THREAD_STATE_KEY,
+                                 THREAD_CPU_TIME_KEY,
+                                 THREAD_ALLOCATED_BYTES_KEY,
+                                 THREAD_USER_TIME_KEY,
+                                 THREAD_BLOCKED_COUNT_KEY,
+                                 THREAD_WAIT_COUNT_KEY),
+                         Arrays.<Key<?>>asList(Key.TIMESTAMP));
     
     /*
      * vm-deadlock-data schema
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/CategorySerializationTest.java	Fri Nov 15 11:14:29 2013 -0500
+++ b/web/common/src/test/java/com/redhat/thermostat/web/common/CategorySerializationTest.java	Mon Nov 18 14:15:56 2013 -0500
@@ -41,6 +41,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 
@@ -83,4 +85,27 @@
         assertEquals("foo-category", cat2.getName());
         assertEquals(barKey, cat2.getKey("bar-key"));
     }
+
+    @Test
+    public void canSerializeDeserializeCategoryWithIndexedKeys() {
+        Key<Boolean> barKey = new Key<>("bar-key");
+        Category<TestObj> cat = new Category<>("foo-category2", TestObj.class,
+                Arrays.<Key<?>>asList(barKey), Arrays.<Key<?>>asList(barKey));
+        String str = gson.toJson(cat, Category.class);
+        @SuppressWarnings("unchecked")
+        Category<TestObj> cat2 = (Category<TestObj>)gson.fromJson(str, Category.class);
+        assertNotSame(cat, cat2);
+        assertTrue(cat.equals(cat2));
+        assertEquals(cat.hashCode(), cat2.hashCode());
+        try {
+            cat2.getKeys().add(new Key<>("testme"));
+            fail("keys must be immutable after deserialization");
+        } catch (UnsupportedOperationException e) {
+            // pass
+        }
+        assertEquals(TestObj.class, cat2.getDataClass());
+        assertEquals("foo-category2", cat2.getName());
+        assertEquals(barKey, cat2.getKey("bar-key"));
+        assertEquals(Arrays.asList(barKey), cat2.getIndexedKeys());
+    }
 }