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>
--- /dev/null
+class com/google/common/collect/ImmutableCollection
+asList
+ ()Lcom/google/common/collect/ImmutableList<TE;>;
+ ()L1com/google/common/collect/ImmutableList<TE;>;
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;
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");
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
*/
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;
}
@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)) {
@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;
}
//--------------------------------------------------------------------------
/**
* 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.