ss: introduce getIteratorOverQuark
authorLoïc Prieur-Drevon <loic.prieurdrevon@gmail.com>
Mon, 18 Jul 2016 17:39:37 +0000 (13:39 -0400)
committerAlexandre Montplaisir <alexmonthy@efficios.com>
Wed, 23 Nov 2016 22:14:26 +0000 (17:14 -0500)
This patch adds a method which returns an iterator over the
intervals of an attribute and a basic unit test.

Change-Id: I8d9d59b1cdf1a80477f24e2849c777c109afbc10
Signed-off-by: Loïc Prieur-Drevon <loic.prieurdrevon@gmail.com>
Reviewed-on: https://git.eclipse.org/r/77546
Reviewed-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Tested-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Reviewed-by: Genevieve Bastien <gbastien+lttng@versatic.net>
Reviewed-by: Hudson CI
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 853357ef6c9d6e83e770f5bdfb201660516fd9e8..d8d23f62aff9a32189b0b13c4f55a000bce1b0ab 100644 (file)
 package org.eclipse.tracecompass.statesystem.core.tests;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 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;
@@ -26,6 +30,7 @@ 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;
@@ -33,6 +38,8 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.google.common.collect.Iterators;
+
 /**
  * Test the {@link StateSystemUtils} class
  *
@@ -128,4 +135,113 @@ public class StateSystemUtilsTest {
 
     }
 
+    /**
+     * Test that 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 testIteratorOverQuark() {
+        ITmfStateSystem ss = fStateSystem;
+        assertNotNull(ss);
+
+        for (int quark = 0; quark < ss.getNbAttributes(); quark++) {
+            Iterator<ITmfStateInterval> iterator = StateSystemUtils.getIteratorOverQuark(ss, quark, Long.MIN_VALUE, Long.MAX_VALUE);
+            ITmfStateInterval prevInterval = null;
+            ITmfStateInterval currInterval = null;
+
+            while (iterator.hasNext()) {
+                currInterval = iterator.next();
+
+                assertEquals(quark, currInterval.getAttribute());
+                if (prevInterval == null) {
+                    /* This is the first interval for this attribute */
+                    assertEquals(currInterval.getStartTime(), ss.getStartTime());
+                } else {
+                    assertEquals(prevInterval.getEndTime() + 1, currInterval.getStartTime());
+                }
+
+                prevInterval = currInterval;
+            }
+
+            assertNotNull("Iterator should have returned at least one interval", currInterval);
+            assertEquals(ss.getCurrentEndTime(), currInterval.getEndTime());
+        }
+    }
+
+    /**
+     * 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
+     */
+    @Test
+    public void testIteratorOverQuarkSubrange() {
+        ITmfStateSystem ss = fStateSystem;
+        assertNotNull(ss);
+
+        int quark;
+        try {
+            quark = ss.getQuarkAbsolute(DUMMY_STRING);
+
+            Iterator<ITmfStateInterval> iterator = StateSystemUtils.getIteratorOverQuark(ss, quark, 1200L, 1400L);
+
+            /* There should be a first interval ranging from 1200L to 1499L */
+            assertTrue(iterator.hasNext());
+            ITmfStateInterval interval = iterator.next();
+            assertNotNull(interval);
+            assertEquals(1200L, interval.getStartTime());
+            assertEquals(1499, interval.getEndTime());
+
+            /* There should not be a next interval */
+            assertFalse(iterator.hasNext());
+        } catch (AttributeNotFoundException e) {
+            fail(e.getMessage());
+        }
+    }
+
+    /**
+     * With the query end > ss.end, query some intervals, then add a few
+     * intervals to the ss such that end now becomes < ss.end and make sure
+     * those new intervals are picked up
+     */
+    @Test
+    public void testIteratorOverQuarkAddMoreIntervals() {
+        try {
+            IStateHistoryBackend backend = StateHistoryBackendFactory.createInMemoryBackend(DUMMY_STRING, START_TIME);
+            ITmfStateSystemBuilder ss = StateSystemFactory.newStateSystem(backend);
+            int quark = ss.getQuarkAbsoluteAndAdd(DUMMY_STRING);
+
+            ss.modifyAttribute(1200L, TmfStateValue.newValueInt(10), quark);
+            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);
+            assertEquals(2, Iterators.size(iterator));
+
+            /* Reset the iterator */
+            iterator = StateSystemUtils.getIteratorOverQuark(ss, quark, 0, 1700L);
+
+            /* Add an interval, updating the ss.end time */
+            ss.closeHistory(2000L);
+
+            /* We should have 3 intervals if we iterate at this point */
+            assertEquals(3, Iterators.size(iterator));
+        } catch (StateValueTypeException e) {
+            fail(e.getMessage());
+        }
+    }
 }
index 82ad0baa954ce03684b7d5ec9841239b1ef62a51..6999544e9032b27e39bcfc6e508f1705b1360b31 100644 (file)
 package org.eclipse.tracecompass.statesystem.core;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;
@@ -279,4 +281,72 @@ public final class StateSystemUtils {
         return null;
     }
 
+    /**
+     * Iterator over the 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$
+        }
+
+        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(start, ss.getStartTime());
+            }
+
+            @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 ITmfStateInterval next() {
+                if (hasNext()) {
+                    try {
+                        return fCurrent = ss.querySingleState(getNextQueryTime(), quark);
+                    } catch (StateSystemDisposedException e) {
+                        /* GOTO throw NoSuchElementException. */
+                    }
+                }
+                throw new NoSuchElementException();
+            }
+        };
+    }
+
 }
This page took 0.026882 seconds and 5 git commands to generate.