segstore: introduce sorted iterators
authorLoïc Prieur-Drevon <loic.prieurdrevon@gmail.com>
Tue, 27 Sep 2016 16:25:40 +0000 (12:25 -0400)
committerJean-Christian Kouame <jean-christian.kouame@ericsson.com>
Mon, 24 Oct 2016 19:07:22 +0000 (15:07 -0400)
add a sorted iterator to the segment store interface.
this will be useful for external memory segment stores
for which the intersecting segments cannot be held and sorted
in main memory, and if external memory stores have optimized
sorted iteration.

Change-Id: I02076daf1721cdf8bdd66f5e892f5c5280e46a3b
Signed-off-by: Loïc Prieur-Drevon <loic.prieurdrevon@gmail.com>
Reviewed-on: https://git.eclipse.org/r/82015
Reviewed-by: Genevieve Bastien <gbastien+lttng@versatic.net>
Tested-by: Genevieve Bastien <gbastien+lttng@versatic.net>
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-by: Hudson CI
Reviewed-by: Jean-Christian Kouame <jean-christian.kouame@ericsson.com>
Tested-by: Jean-Christian Kouame <jean-christian.kouame@ericsson.com>
statesystem/org.eclipse.tracecompass.segmentstore.core.tests/src/org/eclipse/tracecompass/segmentstore/core/tests/AbstractTestSegmentStore.java
statesystem/org.eclipse.tracecompass.segmentstore.core/src/org/eclipse/tracecompass/internal/segmentstore/core/arraylist/ArrayListStore.java
statesystem/org.eclipse.tracecompass.segmentstore.core/src/org/eclipse/tracecompass/internal/segmentstore/core/arraylist/LazyArrayListStore.java
statesystem/org.eclipse.tracecompass.segmentstore.core/src/org/eclipse/tracecompass/internal/segmentstore/core/treemap/TreeMapStore.java
statesystem/org.eclipse.tracecompass.segmentstore.core/src/org/eclipse/tracecompass/segmentstore/core/ISegmentStore.java
statesystem/org.eclipse.tracecompass.segmentstore.core/src/org/eclipse/tracecompass/segmentstore/core/treemap/TreeMapStore.java

index 05818af722fbaeef9710e9497d214684721ce943..3fecaf97de70474096c51533b8329a9450eb7770 100644 (file)
@@ -17,13 +17,17 @@ import static org.junit.Assert.assertTrue;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
 import org.eclipse.tracecompass.segmentstore.core.BasicSegment;
 import org.eclipse.tracecompass.segmentstore.core.ISegment;
 import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
+import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -362,4 +366,40 @@ public abstract class AbstractTestSegmentStore {
         assertEquals(lastExpected, fixture);
     }
 
+    /**
+     * Test to check ordered iterators
+     */
+    @Test
+    public void testSortedIterator() {
+        List<@NonNull Comparator<ISegment>> comparators = new LinkedList<>();
+        comparators.add(SegmentComparators.INTERVAL_END_COMPARATOR);
+        comparators.add(NonNullUtils.checkNotNull(SegmentComparators.INTERVAL_END_COMPARATOR.reversed()));
+        comparators.add(SegmentComparators.INTERVAL_START_COMPARATOR);
+        comparators.add(NonNullUtils.checkNotNull(SegmentComparators.INTERVAL_START_COMPARATOR.reversed()));
+        comparators.add(SegmentComparators.INTERVAL_LENGTH_COMPARATOR);
+        comparators.add(NonNullUtils.checkNotNull(SegmentComparators.INTERVAL_LENGTH_COMPARATOR.reversed()));
+
+        Iterable<ISegment> iterable;
+        for (Comparator<ISegment> comparator : comparators) {
+            iterable = fSegmentStore.iterator(comparator);
+            verifySortedIterable(iterable, 5, comparator);
+            iterable = fSegmentStore.getIntersectingElements(5, comparator);
+            verifySortedIterable(iterable, 3, comparator);
+            iterable = fSegmentStore.getIntersectingElements(7, 14, comparator);
+            verifySortedIterable(iterable, 3, comparator);
+        }
+    }
+
+    private static void verifySortedIterable(Iterable<ISegment> iterable, int expectedSize, Comparator<ISegment> comparator) {
+        // check its size
+        assertEquals(expectedSize, Iterables.size(iterable));
+        Iterator<ISegment> iterator = iterable.iterator();
+        // check the order
+        ISegment prev, current = iterator.next();
+        while (iterator.hasNext()) {
+            prev = current;
+            current = iterator.next();
+            assertTrue(comparator.compare(prev, current) <= 0);
+        }
+    }
 }
\ No newline at end of file
index 8f166f4075fbf728751f43b74b2e4b56c0cc5544..60387b953b3d36513bf4e762274e85ecf25c2f99 100644 (file)
@@ -233,26 +233,6 @@ public class ArrayListStore<@NonNull E extends ISegment> implements ISegmentStor
     // Methods added by ISegmentStore
     // ------------------------------------------------------------------------
 
-    @Override
-    public Iterable<E> getIntersectingElements(long position) {
-        /*
-         * The intervals intersecting 't' are those whose 1) start time is
-         * *lower* than 't' AND 2) end time is *higher* than 't'.
-         */
-        fLock.readLock().lock();
-        try {
-            /*
-             * as fStore is sorted by start then end times, restrict sub array
-             * to elements whose start times <= t as stream.filter won't do it.
-             */
-            int index = Collections.binarySearch(fStore, new BasicSegment(position, Long.MAX_VALUE));
-            index = (index >= 0) ? index : -index - 1;
-            return fStore.subList(0, index).stream().filter(element -> position >= element.getStart() && position <= element.getEnd()).collect(Collectors.toList());
-        } finally {
-            fLock.readLock().unlock();
-        }
-    }
-
     @Override
     public Iterable<E> getIntersectingElements(long start, long end) {
         fLock.readLock().lock();
index 1d6de72ec9d4a3565bc696e3a6df83c8f231c9d2..a9128c7b1773aef6f5c48b968b8ea6f28d658732 100644 (file)
@@ -265,29 +265,6 @@ public class LazyArrayListStore<@NonNull E extends ISegment> implements ISegment
     // Methods added by ISegmentStore
     // ------------------------------------------------------------------------
 
-    @Override
-    public Iterable<E> getIntersectingElements(long position) {
-        fLock.lock();
-        if (fDirty) {
-            sortStore();
-        }
-        /*
-         * The intervals intersecting 't' are those whose 1) start time is
-         * *lower* than 't' AND 2) end time is *higher* than 't'.
-         */
-        try {
-            /*
-             * as fStore is sorted by start then end times, restrict sub array
-             * to elements whose start times <= t as stream.filter won't do it.
-             */
-            int index = Collections.binarySearch(fStore, new BasicSegment(position, Long.MAX_VALUE));
-            index = (index >= 0) ? index : -index - 1;
-            return fStore.subList(0, index).stream().filter(element -> position >= element.getStart() && position <= element.getEnd()).collect(Collectors.toList());
-        } finally {
-            fLock.unlock();
-        }
-    }
-
     @Override
     public Iterable<E> getIntersectingElements(long start, long end) {
         fLock.lock();
index cd1882e6bd4b2281c2660ff35a065d17f26e2c6f..e9a0965ff1f62b7b70b5ed6cecf7d9ae1e4876f5 100644 (file)
@@ -231,22 +231,6 @@ public class TreeMapStore<@NonNull E extends ISegment> implements ISegmentStore<
     // Methods added by ISegmentStore
     // ------------------------------------------------------------------------
 
-    @Override
-    public Iterable<E> getIntersectingElements(long position) {
-        /*
-         * The intervals intersecting 't' are those whose 1) start time is
-         * *lower* than 't' AND 2) end time is *higher* than 't'.
-         */
-        fLock.readLock().lock();
-        try {
-            Iterable<E> matchStarts = Iterables.concat(fStartTimesIndex.asMap().headMap(position, true).values());
-            Iterable<E> matchEnds = Iterables.concat(fEndTimesIndex.asMap().tailMap(position, true).values());
-            return checkNotNull(Sets.intersection(Sets.newHashSet(matchStarts), Sets.newHashSet(matchEnds)));
-        } finally {
-            fLock.readLock().unlock();
-        }
-    }
-
     @Override
     public Iterable<E> getIntersectingElements(long start, long end) {
         fLock.readLock().lock();
index 2e4be6a6594251bffd946911cbfe5bcc9b64f08e..132f08a9a68f3178e1b285fe6d4720cf9af94c2f 100644 (file)
 package org.eclipse.tracecompass.segmentstore.core;
 
 import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+import com.google.common.collect.Lists;
 
 /**
  * Interface for segment-storing backends.
@@ -25,6 +33,18 @@ import java.util.Collection;
  */
 public interface ISegmentStore<E extends ISegment> extends Collection<E> {
 
+    /**
+     * Sorted Iterator
+     *
+     * @param order
+     *            The desired order for the returned iterator
+     * @return An iterator over all the segments in the store in the desired order
+     * @since 1.1
+     */
+    default Iterable<E> iterator(Comparator<ISegment> order){
+        return getIntersectingElements(Long.MIN_VALUE, Long.MAX_VALUE, order);
+    }
+
     /**
      * Retrieve all elements that inclusively cross the given position.
      *
@@ -33,7 +53,25 @@ public interface ISegmentStore<E extends ISegment> extends Collection<E> {
      *            tree's X axis represents time.
      * @return The intervals that cross this position
      */
-    Iterable<E> getIntersectingElements(long position);
+    default Iterable<E> getIntersectingElements(long position){
+        return getIntersectingElements(position, position);
+    }
+
+    /**
+     * Retrieve all elements that inclusively cross the given position, sorted
+     * in the specified order.
+     *
+     * @param position
+     *            The target position. This would represent a timestamp, if the
+     *            tree's X axis represents time.
+     * @param order
+     *            The desired order for the returned iterator
+     * @return The intervals that cross this position
+     * @since 1.1
+     */
+    default Iterable<E> getIntersectingElements(long position, Comparator<ISegment> order) {
+        return getIntersectingElements(position, position, order);
+    }
 
     /**
      * Retrieve all elements that inclusively cross another segment. We define
@@ -54,6 +92,31 @@ public interface ISegmentStore<E extends ISegment> extends Collection<E> {
      */
     Iterable<E> getIntersectingElements(long start, long end);
 
+    /**
+     * Retrieve all elements that inclusively cross another segment, sorted in
+     * the specified order. We define this target segment by its start and end
+     * positions.
+     *
+     * @param start
+     *            The target start position
+     * @param end
+     *            The target end position
+     * @param order
+     *            The desired order for the returned iterator
+     * @return The intervals that cross this position
+     * @since 1.1
+     */
+    default Iterable<E> getIntersectingElements(long start, long end, Comparator<ISegment> order){
+        List<E> list = Lists.newArrayList(getIntersectingElements(start, end));
+        return new Iterable<@NonNull E>() {
+            @Override
+            public Iterator<@NonNull E> iterator() {
+                Collections.sort(list, order);
+                return list.iterator();
+            }
+        };
+    }
+
     /**
      * Dispose the data structure and release any system resources associated
      * with it.
This page took 0.029523 seconds and 5 git commands to generate.