ss: Improve getQuarks() functionality
authorPatrick Tasse <patrick.tasse@gmail.com>
Fri, 29 Apr 2016 17:12:27 +0000 (13:12 -0400)
committerPatrick Tasse <patrick.tasse@gmail.com>
Fri, 13 May 2016 17:43:03 +0000 (13:43 -0400)
Add support for getQuarks() relative to a starting node quark.

Add support for multiple wildcards "*" in pattern.

Add support for parent ".." in pattern.

Change-Id: Ie8d389f7f22fc74912303e1a8bd50c5d8cdfa284
Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-on: https://git.eclipse.org/r/71822
Reviewed-by: Hudson CI
Reviewed-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
common/org.eclipse.tracecompass.common.core/annotations/com/google/common/collect/ImmutableCollection.eea [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/StateSystemTest.java
statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/StateSystem.java
statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/statesystem/core/ITmfStateSystem.java

diff --git a/common/org.eclipse.tracecompass.common.core/annotations/com/google/common/collect/ImmutableCollection.eea b/common/org.eclipse.tracecompass.common.core/annotations/com/google/common/collect/ImmutableCollection.eea
new file mode 100644 (file)
index 0000000..46b7d99
--- /dev/null
@@ -0,0 +1,4 @@
+class com/google/common/collect/ImmutableCollection
+asList
+ ()Lcom/google/common/collect/ImmutableList<TE;>;
+ ()L1com/google/common/collect/ImmutableList<TE;>;
index 4b72531cfff923b25c8929fb9039a74df9e241ee..ef8169a66b7fe286421ab4a9202c6fb911763318 100644 (file)
@@ -19,6 +19,7 @@ import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
@@ -407,6 +408,70 @@ public abstract class StateSystemTest {
         assertEquals(5, list.size());
     }
 
+    @Test
+    public void testGetQuarks_middle_end() {
+        List<Integer> list = fixture.getQuarks(Attributes.THREADS, "*", "*");
+
+        /* There should be 169 threads and 5 sub-attributes per thread */
+        assertEquals(169 * 5, list.size());
+    }
+
+    @Test
+    public void testGetQuarks_empty() {
+        List<Integer> list = fixture.getQuarks();
+
+        assertEquals(Arrays.asList(ITmfStateSystem.ROOT_ATTRIBUTE), list);
+    }
+
+    @Test
+    public void testGetQuarks_relative() {
+        int threadsQuark = INVALID_ATTRIBUTE;
+        try {
+            threadsQuark = fixture.getQuarkAbsolute(Attributes.THREADS);
+        } catch (AttributeNotFoundException e) {
+            fail();
+        }
+        assertNotEquals(INVALID_ATTRIBUTE, threadsQuark);
+
+        List<Integer> list = fixture.getQuarks(threadsQuark, "*", Attributes.EXEC_NAME);
+
+        /* Number of different kernel threads in the trace */
+        assertEquals(169, list.size());
+    }
+
+    @Test
+    public void testGetQuarks_relative_up_wildcard() {
+        int threadsQuark = INVALID_ATTRIBUTE;
+        try {
+            threadsQuark = fixture.getQuarkAbsolute(Attributes.THREADS);
+        } catch (AttributeNotFoundException e) {
+            fail();
+        }
+        assertNotEquals(INVALID_ATTRIBUTE, threadsQuark);
+
+        List<Integer> list = fixture.getQuarks(threadsQuark, "..", Attributes.CPUS, "*");
+
+        /* There should be 2 CPUs */
+        assertEquals(2, list.size());
+    }
+
+    @Test
+    public void testGetQuarks_relative_empty() {
+        int threadsQuark = INVALID_ATTRIBUTE;
+        try {
+            threadsQuark = fixture.getQuarkAbsolute(Attributes.THREADS);
+        } catch (AttributeNotFoundException e) {
+            fail();
+        }
+        assertNotEquals(INVALID_ATTRIBUTE, threadsQuark);
+
+        List<Integer> list = fixture.getQuarks(threadsQuark, new String[0]);
+        assertEquals(Arrays.asList(threadsQuark), list);
+
+        list = fixture.getQuarks(threadsQuark);
+        assertEquals(Arrays.asList(threadsQuark), list);
+    }
+
     @Test
     public void testGetQuarksNoMatch() {
         List<Integer> list = fixture.getQuarks("invalid");
index e95c7d4326b6bd5867efef2b7ad880dc77856776..3e992d483444ddf20cb8837a9517f51d5cdf4ee1 100644 (file)
@@ -38,6 +38,9 @@ import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue.Type;
 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
 
+import com.google.common.collect.ImmutableCollection.Builder;
+import com.google.common.collect.ImmutableSet;
+
 /**
  * This is the core class of the Generic State System. It contains all the
  * methods to build and query a state history. It's exposed externally through
@@ -53,6 +56,9 @@ import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
  */
 public class StateSystem implements ITmfStateSystemBuilder {
 
+    private static final String PARENT = ".."; //$NON-NLS-1$
+    private static final String WILDCARD = "*"; //$NON-NLS-1$
+
     /* References to the inner structures */
     private final AttributeTree attributeTree;
     private final TransientState transState;
@@ -274,16 +280,16 @@ public class StateSystem implements ITmfStateSystemBuilder {
     }
 
     @Override
-    public List<Integer> getSubAttributes(int quark, boolean recursive)
+    public List<@NonNull Integer> getSubAttributes(int quark, boolean recursive)
             throws AttributeNotFoundException {
         return getAttributeTree().getSubAttributes(quark, recursive);
     }
 
     @Override
-    public List<Integer> getSubAttributes(int quark, boolean recursive, String pattern)
+    public List<@NonNull Integer> getSubAttributes(int quark, boolean recursive, String pattern)
             throws AttributeNotFoundException {
         List<Integer> all = getSubAttributes(quark, recursive);
-        List<Integer> ret = new LinkedList<>();
+        List<@NonNull Integer> ret = new LinkedList<>();
         for (Integer attQuark : all) {
             String name = getAttributeName(attQuark.intValue());
             if (name.matches(pattern)) {
@@ -300,87 +306,56 @@ public class StateSystem implements ITmfStateSystemBuilder {
 
     @Override
     public List<@NonNull Integer> getQuarks(String... pattern) {
-        List<@NonNull Integer> quarks = new LinkedList<>();
-        List<String> prefix = new LinkedList<>();
-        List<String> suffix = new LinkedList<>();
-        boolean split = false;
-        String[] prefixStr;
-        String[] suffixStr;
-        List<Integer> directChildren;
-        int startingAttribute;
-
-        /* Fill the "prefix" and "suffix" parts of the pattern around the '*' */
-        for (String entry : pattern) {
-            if (entry.equals("*")) { //$NON-NLS-1$
-                if (split) {
-                    /*
-                     * Split was already true? This means there was more than
-                     * one wildcard. This is not supported, return an empty
-                     * list.
-                     */
-                    return quarks;
-                }
-                split = true;
-                continue;
-            }
+        return getQuarks(ROOT_ATTRIBUTE, pattern);
+    }
 
-            if (split) {
-                suffix.add(entry);
-            } else {
-                prefix.add(entry);
-            }
+    @Override
+    public List<@NonNull Integer> getQuarks(int startingNodeQuark, String... pattern) {
+        Builder<@NonNull Integer> builder = ImmutableSet.builder();
+        if (pattern.length > 0) {
+            getQuarks(builder, startingNodeQuark, Arrays.asList(pattern));
+        } else {
+            builder.add(startingNodeQuark);
         }
-        prefixStr = prefix.toArray(new String[prefix.size()]);
-        suffixStr = suffix.toArray(new String[suffix.size()]);
+        return builder.build().asList();
+    }
 
-        /*
-         * If there was no wildcard, we'll only return the one matching
-         * attribute, if there is one.
-         */
-        if (!split) {
-            int quark;
-            try {
-                quark = getQuarkAbsolute(prefixStr);
-            } catch (AttributeNotFoundException e) {
-                /* It's fine, we'll just return the empty List */
-                return quarks;
+    private void getQuarks(Builder<@NonNull Integer> builder, int quark, List<String> pattern) {
+        try {
+            String element = pattern.get(0);
+            if (element == null) {
+                return;
             }
-            quarks.add(quark);
-            return quarks;
-        }
-
-        if (prefix.isEmpty()) {
-            /*
-             * If 'prefix' is empty, this means the wildcard was the first
-             * element. Look for the root node's sub-attributes.
-             */
-            startingAttribute = ROOT_ATTRIBUTE;
-        } else {
-            startingAttribute = optQuarkAbsolute(prefixStr);
-            if (startingAttribute == INVALID_ATTRIBUTE) {
-                /* That attribute path did not exist, return the empty array */
-                return quarks;
+            List<String> remainder = pattern.subList(1, pattern.size());
+            if (remainder.isEmpty()) {
+                if (element.equals(WILDCARD)) {
+                    builder.addAll(getSubAttributes(quark, false));
+                } else if (element.equals(PARENT)){
+                    builder.add(getParentAttributeQuark(quark));
+                } else {
+                    int subQuark = optQuarkRelative(quark, element);
+                    if (subQuark != INVALID_ATTRIBUTE) {
+                        builder.add(subQuark);
+                    }
+                }
+            } else {
+                if (element.equals(WILDCARD)) {
+                    for (@NonNull Integer subquark : getSubAttributes(quark, false)) {
+                        getQuarks(builder, subquark, remainder);
+                    }
+                } else if (element.equals(PARENT)){
+                    getQuarks(builder, getParentAttributeQuark(quark), remainder);
+                } else {
+                    int subQuark = optQuarkRelative(quark, element);
+                    if (subQuark != INVALID_ATTRIBUTE) {
+                        getQuarks(builder, subQuark, remainder);
+                    }
+                }
             }
-        }
-        try {
-            directChildren = getSubAttributes(startingAttribute, false);
         } catch (AttributeNotFoundException e) {
-            /* Should not happen, starting attribute is a valid quark */
-            throw new IllegalStateException();
+            /* The starting node quark is out of range */
+            throw new IndexOutOfBoundsException(String.format("Index: %d, Size: %d", quark, getNbAttributes())); //$NON-NLS-1$
         }
-
-        /*
-         * Iterate of all the sub-attributes, and only keep those who match the
-         * 'suffix' part of the initial pattern.
-         */
-        for (int childQuark : directChildren) {
-            int matchingQuark = optQuarkRelative(childQuark, suffixStr);
-            if (matchingQuark != INVALID_ATTRIBUTE) {
-                quarks.add(matchingQuark);
-            }
-        }
-
-        return quarks;
     }
 
     //--------------------------------------------------------------------------
index 34a607b48fc93baa4d01885788cb2cf70b9419fe..d5b4385b722e8d3af02d5899ae306f89704a618f 100644 (file)
@@ -254,30 +254,59 @@ public interface ITmfStateSystem {
 
     /**
      * Batch quark-retrieving method. This method allows you to specify a path
-     * pattern which includes a wildcard "*" somewhere. It will check all the
-     * existing attributes in the attribute tree and return those who match the
-     * pattern.
-     *
+     * pattern which can include wildcard "*" or parent ".." elements. It will
+     * check all the existing attributes in the attribute tree and return those
+     * who match the pattern.
+     * <p>
      * For example, passing ("Threads", "*", "Exec_mode") will return the list
      * of quarks for attributes "Threads/1000/Exec_mode",
      * "Threads/1500/Exec_mode", and so on, depending on what exists at this
      * time in the attribute tree.
-     *
-     * If no wildcard is specified, the behavior is the same as
-     * getQuarkAbsolute() (except it will return a List with one entry). This
+     * <p>
+     * If no wildcard or parent element is specified, the behavior is the same
+     * as getQuarkAbsolute() (except it will return a List with one entry, or an
+     * empty list if there is no match instead of throwing an exception). This
      * method will never create new attributes.
      *
-     * Only one wildcard "*" is supported at this time.
-     *
      * @param pattern
-     *            The array of strings representing the pattern to look for. It
-     *            should ideally contain one entry that is only a "*".
-     * @return A List of attribute quarks, representing attributes that matched
-     *         the pattern. If no attribute matched, the list will be empty (but
-     *         not null).
+     *            The array of strings representing the pattern to look for.
+     * @return A List of unique attribute quarks, representing attributes that
+     *         matched the pattern. If no attribute matched, the list will be
+     *         empty (but not null). If the pattern is empty,
+     *         {@link #ROOT_ATTRIBUTE} is returned in the list.
      */
     @NonNull List<@NonNull Integer> getQuarks(String... pattern);
 
+    /**
+     * Relative batch quark-retrieving method. This method allows you to specify
+     * a path pattern which can include wildcard "*" or parent ".." elements. It
+     * will check all the existing attributes in the attribute tree and return
+     * those who match the pattern.
+     * <p>
+     * For example, passing (5, "Threads", "*", "Exec_mode") will return the
+     * list of quarks for attributes "<path of quark 5>/Threads/1000/Exec_mode",
+     * "<path of quark 5>/Threads/1500/Exec_mode", and so on, depending on what
+     * exists at this time in the attribute tree.
+     * <p>
+     * If no wildcard or parent element is specified, the behavior is the same
+     * as getQuarkRelative() (except it will return a List with one entry, or an
+     * empty list if there is no match instead of throwing an exception). This
+     * method will never create new attributes.
+     *
+     * @param startingNodeQuark
+     *            The quark of the attribute from which 'pattern' originates.
+     * @param pattern
+     *            The array of strings representing the pattern to look for.
+     * @return A List of unique attribute quarks, representing attributes that
+     *         matched the pattern. If no attribute matched, the list will be
+     *         empty (but not null). If the pattern is empty, the starting node
+     *         quark is returned in the list.
+     * @throws IndexOutOfBoundsException
+     *             If the starting node quark is out of range
+     * @since 2.0
+     */
+    @NonNull List<@NonNull Integer> getQuarks(int startingNodeQuark, String... pattern);
+
     /**
      * Return the name assigned to this quark. This returns only the "basename",
      * not the complete path to this attribute.
This page took 0.030353 seconds and 5 git commands to generate.