ss: Change getIteratorOverQuark to a public class
authorLoïc Prieur-Drevon <loic.prieurdrevon@gmail.com>
Wed, 30 Nov 2016 18:53:24 +0000 (13:53 -0500)
committerAlexandre Montplaisir <alexmonthy@efficios.com>
Thu, 1 Dec 2016 22:16:51 +0000 (17:16 -0500)
This patch allows iteration to go backwards and forwards,
introduces a unit test and uses the new iterator for:
KernelThreadInformationProvider.getExecutableName

Change-Id: I41f35e30bd1984662f55b8809e2497a6c19d5468
Signed-off-by: Loïc Prieur-Drevon <loic.prieurdrevon@gmail.com>
Signed-off-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Reviewed-on: https://git.eclipse.org/r/85798
Reviewed-by: Genevieve Bastien <gbastien+lttng@versatic.net>
Reviewed-by: Hudson CI
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernel/KernelThreadInformationProvider.java
statesystem/org.eclipse.tracecompass.statesystem.core.tests/src/org/eclipse/tracecompass/statesystem/core/tests/StateSystemUtilsTest.java
statesystem/org.eclipse.tracecompass.statesystem.core/src/org/eclipse/tracecompass/statesystem/core/StateSystemUtils.java

index dd4e20f6914034603852870cc41f42d1f8fd7c07..e57861d7977aa74c96b2d918fc889810e8872940 100644 (file)
@@ -24,6 +24,7 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
 import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
+import org.eclipse.tracecompass.statesystem.core.StateSystemUtils.QuarkIterator;
 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
 import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
 import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
@@ -148,21 +149,16 @@ public final class KernelThreadInformationProvider {
         if (ss == null) {
             return null;
         }
-        Integer execNameNode;
-        try {
-            execNameNode = ss.getQuarkAbsolute(Attributes.THREADS, threadId.toString(), Attributes.EXEC_NAME);
-            List<ITmfStateInterval> execNameIntervals = StateSystemUtils.queryHistoryRange(ss, execNameNode, ss.getStartTime(), ss.getCurrentEndTime());
-
-            ITmfStateValue execNameValue;
-            String execName = null;
-            for (ITmfStateInterval interval : execNameIntervals) {
-                execNameValue = interval.getStateValue();
-                if (execNameValue.getType().equals(Type.STRING)) {
-                    execName = execNameValue.unboxStr();
-                }
+        int execNameNode = ss.optQuarkAbsolute(Attributes.THREADS, threadId.toString(), Attributes.EXEC_NAME);
+        if (execNameNode == ITmfStateSystem.INVALID_ATTRIBUTE) {
+            return null;
+        }
+        QuarkIterator reversedIterator = new QuarkIterator(ss, execNameNode, ss.getCurrentEndTime());
+        while (reversedIterator.hasPrevious()) {
+            ITmfStateValue nameInterval = reversedIterator.previous().getStateValue();
+            if (nameInterval.getType() == Type.STRING) {
+                return nameInterval.unboxStr();
             }
-            return execName;
-        } catch (AttributeNotFoundException | StateSystemDisposedException | TimeRangeException e) {
         }
         return null;
     }
index d8d23f62aff9a32189b0b13c4f55a000bce1b0ab..240e83a02873ffdca1e2d2c78efe30e521722637 100644 (file)
@@ -19,18 +19,16 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.util.Iterator;
-
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
 import org.eclipse.tracecompass.statesystem.core.StateSystemFactory;
 import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
+import org.eclipse.tracecompass.statesystem.core.StateSystemUtils.QuarkIterator;
 import org.eclipse.tracecompass.statesystem.core.backend.IStateHistoryBackend;
 import org.eclipse.tracecompass.statesystem.core.backend.StateHistoryBackendFactory;
 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
 import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
-import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
 import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
 import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
@@ -149,7 +147,7 @@ public class StateSystemUtilsTest {
         assertNotNull(ss);
 
         for (int quark = 0; quark < ss.getNbAttributes(); quark++) {
-            Iterator<ITmfStateInterval> iterator = StateSystemUtils.getIteratorOverQuark(ss, quark, Long.MIN_VALUE, Long.MAX_VALUE);
+            QuarkIterator iterator = new QuarkIterator(ss, quark, Long.MIN_VALUE);
             ITmfStateInterval prevInterval = null;
             ITmfStateInterval currInterval = null;
 
@@ -172,18 +170,6 @@ public class StateSystemUtilsTest {
         }
     }
 
-    /**
-     * Test that the correct exception is thrown by getIteratorOverQuark when
-     * the lower bound argument is strictly greater than the upper bound
-     * argument
-     */
-    @Test(expected = TimeRangeException.class)
-    public void testIteratorOverQuarkTimeRangeException() {
-        ITmfStateSystem ss = fStateSystem;
-        assertNotNull(ss);
-        StateSystemUtils.getIteratorOverQuark(ss, 0, ss.getCurrentEndTime(), ss.getStartTime());
-    }
-
     /**
      * Test that getIteratorOverQuark returns the correct intervals for a range
      * included in the state system range
@@ -197,14 +183,14 @@ public class StateSystemUtilsTest {
         try {
             quark = ss.getQuarkAbsolute(DUMMY_STRING);
 
-            Iterator<ITmfStateInterval> iterator = StateSystemUtils.getIteratorOverQuark(ss, quark, 1200L, 1400L);
+            QuarkIterator iterator = new QuarkIterator(ss, quark, 1800L);
 
-            /* There should be a first interval ranging from 1200L to 1499L */
+            /* There should be one interval ranging from 1500L to 2000L */
             assertTrue(iterator.hasNext());
             ITmfStateInterval interval = iterator.next();
             assertNotNull(interval);
-            assertEquals(1200L, interval.getStartTime());
-            assertEquals(1499, interval.getEndTime());
+            assertEquals(1500L, interval.getStartTime());
+            assertEquals(2000L, interval.getEndTime());
 
             /* There should not be a next interval */
             assertFalse(iterator.hasNext());
@@ -229,11 +215,11 @@ public class StateSystemUtilsTest {
             ss.modifyAttribute(1500L, TmfStateValue.newValueInt(20), quark);
 
             /* We should have 2 intervals if we iterate at this point */
-            Iterator<ITmfStateInterval> iterator = StateSystemUtils.getIteratorOverQuark(ss, quark, 0, 1700L);
+            QuarkIterator iterator = new QuarkIterator(ss, quark, 0);
             assertEquals(2, Iterators.size(iterator));
 
             /* Reset the iterator */
-            iterator = StateSystemUtils.getIteratorOverQuark(ss, quark, 0, 1700L);
+            iterator = new QuarkIterator(ss, quark, 0);
 
             /* Add an interval, updating the ss.end time */
             ss.closeHistory(2000L);
@@ -244,4 +230,41 @@ public class StateSystemUtilsTest {
             fail(e.getMessage());
         }
     }
+
+    /**
+     * Test that the reverse iterator returns the correct intervals:
+     * <ul>
+     * <li>intervals for the correct quark</li>
+     * <li>ordered intervals</li>
+     * <li>intervals covering the correct time range</li>
+     * </ul>
+     */
+    @Test
+    public void testIteratorOverQuarkReversed() {
+        ITmfStateSystem ss = fStateSystem;
+        assertNotNull(ss);
+
+        for (int quark = 0; quark < ss.getNbAttributes(); quark++) {
+            QuarkIterator iterator = new QuarkIterator(ss, quark, Long.MAX_VALUE);
+            ITmfStateInterval prevInterval = null;
+            ITmfStateInterval currInterval = null;
+
+            while (iterator.hasPrevious()) {
+                currInterval = iterator.previous();
+
+                assertEquals(quark, currInterval.getAttribute());
+                if (prevInterval == null) {
+                    /* This is the first interval for this attribute */
+                    assertEquals(currInterval.getEndTime(), ss.getCurrentEndTime());
+                } else {
+                    assertEquals(prevInterval.getStartTime() - 1, currInterval.getEndTime());
+                }
+
+                prevInterval = currInterval;
+            }
+
+            assertNotNull("Iterator should have returned at least one interval", currInterval);
+            assertEquals(ss.getStartTime(), currInterval.getStartTime());
+        }
+    }
 }
index 6999544e9032b27e39bcfc6e508f1705b1360b31..8c90bece697b49f1d8e637839f280bc080bad11f 100644 (file)
@@ -35,6 +35,7 @@ import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
  * Provide utility methods for the state system
  *
  * @author Geneviève Bastien
+ * @author Loïc Prieur-Drevon
  */
 @NonNullByDefault
 public final class StateSystemUtils {
@@ -282,71 +283,114 @@ public final class StateSystemUtils {
     }
 
     /**
-     * Iterator over the intervals of a given attribute. Not thread-safe.
+     * Iterator class to allow 2-way iteration over intervals of a given
+     * attribute. Not thread-safe!
      *
-     * @param ss
-     *            The state system on which to query intervals
-     *
-     * @param quark
-     *            The key to the attribute to iterate over
-     * @param start
-     *            The begin of the range of intervals to iterate over, if start
-     *            is before the state system's start time, the iteration will
-     *            begin at the state system's start time.
-     * @param end
-     *            The end of the range of intervals to iterate over, it can be
-     *            greater than the current state system's end time, iteration
-     *            will end at the smallest of the two.
-     * @return an Iterator over the intervals of a given attribute, with
-     *         intervals ordered
-     * @throws TimeRangeException
-     *             If end < start.
      * @since 2.1
      */
-    public static Iterator<ITmfStateInterval> getIteratorOverQuark(ITmfStateSystem ss, int quark, long start, long end) {
-        if (end < start) {
-            throw new TimeRangeException("iterateOverQuark: end < start !"); //$NON-NLS-1$
+    public static class QuarkIterator implements Iterator<ITmfStateInterval> {
+
+        private final ITmfStateSystem fSS;
+        private final int fQuark;
+        private final long fInitialTime;
+
+        private @Nullable ITmfStateInterval fCurrent;
+
+        /**
+         * Constructor
+         *
+         * @param ss
+         *            The state system on which to query intervals
+         * @param quark
+         *            The key to the attribute to iterate over
+         * @param initialTime
+         *            The timestamp that the first returned interval will
+         *            intersect. This timestamp can be smaller than the
+         *            StateSystem's start time, in which case, iteration will
+         *            start at the StateSystem's start, on bigger than the
+         *            StateSystem's current end time, in which case iteration
+         *            will start at the StateSystem's current end time.
+         * @throws TimeRangeException
+         *             If end < start.
+         * @since 2.1
+         */
+        public QuarkIterator(ITmfStateSystem ss, int quark, long initialTime) {
+            fSS = ss;
+            fQuark = quark;
+            fInitialTime = initialTime;
         }
 
-        return new Iterator<ITmfStateInterval>() {
-            private @Nullable ITmfStateInterval fCurrent;
+        private long getNextQueryTime() {
+            if (fCurrent != null) {
+                return (fCurrent.getEndTime() + 1);
+            }
+            /* Iteration has not started yet */
+            return Long.max(fInitialTime, fSS.getStartTime());
+        }
 
-            private long getNextQueryTime() {
-                if (fCurrent != null) {
-                    return fCurrent.getEndTime() + 1;
-                }
-                /* Iteration has not started yet */
-                return Long.max(start, ss.getStartTime());
+        private long getPreviousQueryTime() {
+            if (fCurrent != null) {
+                return fCurrent.getStartTime() - 1;
             }
+            /* Iteration has not started yet */
+            return Long.min(fInitialTime, fSS.getCurrentEndTime());
+        }
 
-            @Override
-            public boolean hasNext() {
-                /*
-                 * Compute the query's real end time here, to update it if the
-                 * iterator is used during state system build
-                 */
-                long realEnd = Long.min(end, ss.getCurrentEndTime());
-
-                /*
-                 * Ensure that the next query time falls within state system and
-                 * query time range. By definition getNextQueryTime() is larger
-                 * than the state system's start time.
-                 */
-                return getNextQueryTime() <= realEnd;
+        @Override
+        public boolean hasNext() {
+            /*
+             * Ensure that the next query time falls within state system and
+             * query time range. By definition getNextQueryTime() is larger than
+             * the state system's start time.
+             */
+            return (getNextQueryTime() <= fSS.getCurrentEndTime());
+        }
+
+        @Override
+        public ITmfStateInterval next() {
+            if (hasNext()) {
+                try {
+                    fCurrent = fSS.querySingleState(getNextQueryTime(), fQuark);
+                    return fCurrent;
+                } catch (StateSystemDisposedException e) {
+                    /* GOTO throw NoSuchElementException. */
+                }
             }
+            throw new NoSuchElementException();
+        }
+
+        /**
+         * Returns true if the iteration has more previous elements. (In other
+         * words, returns true if previous() would return an element rather than
+         * throwing an exception.)
+         *
+         * @return true if the iteration has more previous elements
+         */
+        public boolean hasPrevious() {
+            /*
+             * Ensure that the next query time falls within state system and
+             * query time range. By definition getPreviousQueryTime() is smaller
+             * than the state system's end time.
+             */
+            return (getPreviousQueryTime() >= fSS.getStartTime());
+        }
 
-            @Override
-            public ITmfStateInterval next() {
-                if (hasNext()) {
-                    try {
-                        return fCurrent = ss.querySingleState(getNextQueryTime(), quark);
-                    } catch (StateSystemDisposedException e) {
-                        /* GOTO throw NoSuchElementException. */
-                    }
+        /**
+         * Returns the previous element in the iteration.
+         *
+         * @return the previous element in the iteration
+         */
+        public ITmfStateInterval previous() {
+            if (hasPrevious()) {
+                try {
+                    fCurrent = fSS.querySingleState(getPreviousQueryTime(), fQuark);
+                    return fCurrent;
+                } catch (StateSystemDisposedException e) {
+                    /* GOTO throw NoSuchElementException. */
                 }
-                throw new NoSuchElementException();
             }
-        };
+            throw new NoSuchElementException();
+        }
     }
 
 }
This page took 0.029338 seconds and 5 git commands to generate.