From: Patrick Tasse Date: Fri, 29 Apr 2016 17:12:27 +0000 (-0400) Subject: ss: Improve getQuarks() functionality X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=aa315d8b403515975f249f30e3c804dfb8854b5e;p=deliverable%2Ftracecompass.git ss: Improve getQuarks() functionality 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 Reviewed-on: https://git.eclipse.org/r/71822 Reviewed-by: Hudson CI Reviewed-by: Alexandre Montplaisir Reviewed-by: Matthew Khouzam Tested-by: Matthew Khouzam --- 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 index 0000000000..46b7d99af0 --- /dev/null +++ b/common/org.eclipse.tracecompass.common.core/annotations/com/google/common/collect/ImmutableCollection.eea @@ -0,0 +1,4 @@ +class com/google/common/collect/ImmutableCollection +asList + ()Lcom/google/common/collect/ImmutableList; + ()L1com/google/common/collect/ImmutableList; diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/StateSystemTest.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/StateSystemTest.java index 4b72531cff..ef8169a66b 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/StateSystemTest.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/StateSystemTest.java @@ -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 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 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 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 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 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 list = fixture.getQuarks("invalid"); diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/StateSystem.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/StateSystem.java index e95c7d4326..3e992d4834 100644 --- a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/StateSystem.java +++ b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/internal/statesystem/core/StateSystem.java @@ -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 getSubAttributes(int quark, boolean recursive) + public List<@NonNull Integer> getSubAttributes(int quark, boolean recursive) throws AttributeNotFoundException { return getAttributeTree().getSubAttributes(quark, recursive); } @Override - public List getSubAttributes(int quark, boolean recursive, String pattern) + public List<@NonNull Integer> getSubAttributes(int quark, boolean recursive, String pattern) throws AttributeNotFoundException { List all = getSubAttributes(quark, recursive); - List 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 prefix = new LinkedList<>(); - List suffix = new LinkedList<>(); - boolean split = false; - String[] prefixStr; - String[] suffixStr; - List 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 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 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; } //-------------------------------------------------------------------------- diff --git a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/statesystem/core/ITmfStateSystem.java b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/statesystem/core/ITmfStateSystem.java index 34a607b48f..d5b4385b72 100644 --- a/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/statesystem/core/ITmfStateSystem.java +++ b/statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/statesystem/core/ITmfStateSystem.java @@ -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. + *

* 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 + *

+ * 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. + *

+ * For example, passing (5, "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 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.