timing: ss statistics use the common statistics
authorGeneviève Bastien <gbastien+lttng@versatic.net>
Tue, 17 Jan 2017 16:39:19 +0000 (11:39 -0500)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Mon, 30 Jan 2017 14:02:55 +0000 (09:02 -0500)
This patch has the SegmentStoreStatistics class use a Statistics object
instead of calculating the statistics themselves (it will later be
deprecated entirely, but there are too many things to fix for one patch)

It deprecates the methods of the AbstractSegmentStoreAnalysis that used
the SegmentStoreStatistics class.

It also deprecates the current abstract statistics view and viewer in
the UI and replaces them with one using the new statistics class.

Change-Id: Idfdeed3198d70d0eae7b75b90453f67ddb138809
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/88901
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
17 files changed:
analysis/org.eclipse.tracecompass.analysis.os.linux.core.tests/src/org/eclipse/tracecompass/analysis/os/linux/core/tests/latency/SyscallStatsAnalysisTest.java
analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyStatisticsTableAnalysisTest.java
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/statistics/SystemCallLatencyStatisticsView.java
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/latency/statistics/SystemCallLatencyStatisticsViewer.java
analysis/org.eclipse.tracecompass.analysis.timing.core.tests/META-INF/MANIFEST.MF
analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/statistics/AbstractStatsAnalysisTest.java
analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/statistics/OfflineStatisticsCalculator.java [deleted file]
analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/statistics/SegmentStoreStatisticsTest.java
analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/analysis/timing/core/segmentstore/statistics/AbstractSegmentStatisticsAnalysis.java
analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/analysis/timing/core/segmentstore/statistics/SegmentStoreStatistics.java
analysis/org.eclipse.tracecompass.analysis.timing.ui/META-INF/MANIFEST.MF
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentStoreStatisticsView.java
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentStoreStatisticsViewer.java
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentsStatisticsView.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentsStatisticsViewer.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/latency/PatternStatisticsView.java
tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/latency/PatternStatisticsViewer.java

index a35bc44df5e19c432150f0e08df7ca48ed88cab4..2d67db6d3b347a32d87129ce78d94b5b62ddd018 100644 (file)
@@ -12,9 +12,11 @@ package org.eclipse.tracecompass.analysis.os.linux.core.tests.latency;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
-import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.SegmentStoreStatistics;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
 import org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.SystemCallLatencyAnalysis;
 import org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.statistics.SystemCallLatencyStatisticsAnalysisModule;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
@@ -79,9 +81,9 @@ public class SyscallStatsAnalysisTest {
     public void testSmallTraceSequential() {
         final SystemCallLatencyStatisticsAnalysisModule syscallStatsModule = fSyscallStatsModule;
         assertNotNull(syscallStatsModule);
-        SegmentStoreStatistics totalStats = syscallStatsModule.getTotalStats();
+        IStatistics<@NonNull ISegment> totalStats = syscallStatsModule.getStatsTotal();
         assertNotNull(totalStats);
-        assertEquals(1801, totalStats.getNbSegments());
+        assertEquals(1801, totalStats.getNbElements());
         assertEquals(5904091700L, totalStats.getMax());
     }
 }
index 7143045c73c78fffc25eafeea1c11e8b31bb62c3..ca2d3cfd7a9aeded73cf45d25481a4eb35fc85f9 100644 (file)
@@ -39,7 +39,7 @@ import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
 import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
 import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
 import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsView;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentsStatisticsView;
 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.statistics.SystemCallLatencyStatisticsView;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers;
@@ -213,7 +213,7 @@ public class SystemCallLatencyStatisticsTableAnalysisTest {
         assertNotNull(os);
         IViewPart viewPart = view.getReference().getView(true);
         assertTrue(viewPart instanceof SystemCallLatencyStatisticsView);
-        Class<@NonNull AbstractSegmentStoreStatisticsView> clazz = AbstractSegmentStoreStatisticsView.class;
+        Class<@NonNull AbstractSegmentsStatisticsView> clazz = AbstractSegmentsStatisticsView.class;
         Method method = clazz.getDeclaredMethod("exportToTsv", java.io.OutputStream.class);
         method.setAccessible(true);
         final Exception[] except = new Exception[1];
index 509809edb88c6662d050bed36369520904444b26..951991e7c8cfc2998b40e8729a3f102012948c05 100644 (file)
@@ -12,8 +12,8 @@
 package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.statistics;
 
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsView;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentsStatisticsView;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
 
 /**
  * View to display latency statistics.
@@ -21,13 +21,13 @@ import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics
  * @author Bernd Hufmann
  *
  */
-public class SystemCallLatencyStatisticsView extends AbstractSegmentStoreStatisticsView {
+public class SystemCallLatencyStatisticsView extends AbstractSegmentsStatisticsView {
 
     /** The view ID*/
     public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.ui.views.latency.statsview"; //$NON-NLS-1$
 
     @Override
-    protected AbstractSegmentStoreStatisticsViewer createSegmentStoreStatisticsViewer(Composite parent) {
+    protected AbstractTmfTreeViewer createSegmentStoreStatisticsViewer(Composite parent) {
         return new SystemCallLatencyStatisticsViewer(parent);
     }
 
index 26f70c80cda244472af9e609e92a6d6df5705de1..e6f13d38f7efe8a892e8b03976cfc4e103605cc2 100644 (file)
@@ -16,7 +16,7 @@ import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentsStatisticsViewer;
 import org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.statistics.SystemCallLatencyStatisticsAnalysisModule;
 import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
 
@@ -26,7 +26,7 @@ import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
  * @author Bernd Hufmann
  *
  */
-public class SystemCallLatencyStatisticsViewer extends AbstractSegmentStoreStatisticsViewer {
+public class SystemCallLatencyStatisticsViewer extends AbstractSegmentsStatisticsViewer {
 
     private static final String SYSCALL_LEVEL = checkNotNull(Messages.LatencyStatistics_SyscallLevelName);
 
index c3a5e67189777cfb77d1ce32891e1eb49729fcea..50c85c8ade13c7cb0595fa3dfad5b38e2ecfd1c6 100644 (file)
@@ -17,11 +17,12 @@ Require-Bundle: org.junit;bundle-version="4.0.0",
  org.eclipse.tracecompass.tmf.ctf.core,
  org.eclipse.tracecompass.tmf.ctf.core.tests,
  org.eclipse.core.resources,
- org.eclipse.tracecompass.analysis.timing.core;bundle-version="1.0.0"
+ org.eclipse.tracecompass.analysis.timing.core
 Import-Package: com.google.common.collect,
- org.eclipse.tracecompass.testtraces.ctf;version="1.0.0"
+ org.eclipse.tracecompass.testtraces.ctf
 Export-Package: org.eclipse.tracecompass.analysis.timing.core.tests,
  org.eclipse.tracecompass.analysis.timing.core.tests.callgraph,
  org.eclipse.tracecompass.analysis.timing.core.tests.flamegraph,
- org.eclipse.tracecompass.analysis.timing.core.tests.segmentstore.statistics
+ org.eclipse.tracecompass.analysis.timing.core.tests.segmentstore.statistics,
+ org.eclipse.tracecompass.analysis.timing.core.tests.statistics
 Bundle-Activator: org.eclipse.tracecompass.analysis.timing.core.tests.Activator
index a42c21c96786d07d5c902c53420030f4b9316d19..f0ea5fd58f4ff8a51b12bf8c3c54873e37294609 100644 (file)
@@ -20,7 +20,8 @@ import java.util.Map;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.AbstractSegmentStatisticsAnalysis;
-import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.SegmentStoreStatistics;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
 import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.tests.stubs.trace.xml.TmfXmlTraceStub;
@@ -93,10 +94,10 @@ public class AbstractStatsAnalysisTest {
     public void testTotalStats() throws TmfAnalysisException {
         TmfXmlTraceStub trace = new TmfXmlTraceStubNs();
         StubSegmentStatisticsAnalysis fixture = getValidSegmentStats(trace);
-        SegmentStoreStatistics totalStats = fixture.getTotalStats();
+        IStatistics<@NonNull ISegment> totalStats = fixture.getStatsTotal();
         assertNotNull(totalStats);
         // no need to test the content much as it is tested in the other test.
-        assertEquals(StubSegmentStatisticsAnalysis.SIZE, totalStats.getNbSegments());
+        assertEquals(StubSegmentStatisticsAnalysis.SIZE, totalStats.getNbElements());
         trace.dispose();
         fixture.dispose();
     }
@@ -112,15 +113,15 @@ public class AbstractStatsAnalysisTest {
     public void testPerTypeStats() throws TmfAnalysisException {
         TmfXmlTraceStub trace = new TmfXmlTraceStubNs();
         StubSegmentStatisticsAnalysis fixture = getValidSegmentStats(trace);
-        Map<@NonNull String, @NonNull SegmentStoreStatistics> perTypeStats = fixture.getPerSegmentTypeStats();
+        Map<@NonNull String, IStatistics<@NonNull ISegment>> perTypeStats = fixture.getStatsPerType();
         assertNotNull(perTypeStats);
         // no need to test the content much as it is tested in the other test.
         assertEquals(2, perTypeStats.size());
         assertEquals(ImmutableSet.<String> of("odd", "even"), perTypeStats.keySet());
-        SegmentStoreStatistics segmentStoreStatistics = perTypeStats.get("even");
+        IStatistics<@NonNull ISegment> segmentStoreStatistics = perTypeStats.get("even");
         assertNotNull(segmentStoreStatistics);
         // starts with 0  so size + 1
-        assertEquals(StubSegmentStatisticsAnalysis.SIZE / 2 + 1, segmentStoreStatistics.getNbSegments());
+        assertEquals(StubSegmentStatisticsAnalysis.SIZE / 2 + 1, segmentStoreStatistics.getNbElements());
         trace.dispose();
         fixture.dispose();
     }
@@ -136,13 +137,13 @@ public class AbstractStatsAnalysisTest {
     public void testPartialStats() throws TmfAnalysisException {
         TmfXmlTraceStub trace = new TmfXmlTraceStubNs();
         StubSegmentStatisticsAnalysis fixture = getValidSegmentStats(trace);
-        SegmentStoreStatistics totalStats = fixture.getTotalStatsForRange(100, 1100, new NullProgressMonitor());
+        IStatistics<@NonNull ISegment> totalStats = fixture.getStatsForRange(100, 1100, new NullProgressMonitor());
         assertNotNull(totalStats);
         // no need to test the content much as it is tested in the other test.
 
         // 1051 = 1001 where start is between start and end + 50 overlapping
         // start
-        assertEquals(1051, totalStats.getNbSegments());
+        assertEquals(1051, totalStats.getNbElements());
         trace.dispose();
         fixture.dispose();
     }
@@ -158,15 +159,15 @@ public class AbstractStatsAnalysisTest {
     public void testPartialPerTypeStats() throws TmfAnalysisException {
         TmfXmlTraceStub trace = new TmfXmlTraceStubNs();
         StubSegmentStatisticsAnalysis fixture = getValidSegmentStats(trace);
-        Map<@NonNull String, @NonNull SegmentStoreStatistics> perTypeStats = fixture.getPerSegmentTypeStatsForRange(100, 1100, new NullProgressMonitor());
+        Map<@NonNull String, IStatistics<@NonNull ISegment>> perTypeStats = fixture.getStatsPerTypeForRange(100, 1100, new NullProgressMonitor());
         assertNotNull(perTypeStats);
         // no need to test the content much as it is tested in the other test.
         assertEquals(2, perTypeStats.size());
         assertEquals(ImmutableSet.<String> of("odd", "even"), perTypeStats.keySet());
-        SegmentStoreStatistics segmentStoreStatistics = perTypeStats.get("even");
+        IStatistics<@NonNull ISegment> segmentStoreStatistics = perTypeStats.get("even");
         assertNotNull(segmentStoreStatistics);
         // 526 = 1051/2+1 = see explanation of 1051 in #testPartialStats
-        assertEquals(526, segmentStoreStatistics.getNbSegments());
+        assertEquals(526, segmentStoreStatistics.getNbElements());
         trace.dispose();
         fixture.dispose();
     }
@@ -183,7 +184,7 @@ public class AbstractStatsAnalysisTest {
         StubSegmentStatisticsAnalysis fixture = getValidSegmentStats(trace);
         NullProgressMonitor monitor = new NullProgressMonitor();
         monitor.setCanceled(true);
-        Map<@NonNull String, @NonNull SegmentStoreStatistics> perTypeStats = fixture.getPerSegmentTypeStatsForRange(100, 1100, monitor);
+        Map<@NonNull String, IStatistics<@NonNull ISegment>> perTypeStats = fixture.getStatsPerTypeForRange(100, 1100, monitor);
         assertEquals(Collections.emptyMap(), perTypeStats);
         trace.dispose();
         fixture.dispose();
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/statistics/OfflineStatisticsCalculator.java b/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/statistics/OfflineStatisticsCalculator.java
deleted file mode 100644 (file)
index 432eb6e..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Ericsson
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *******************************************************************************/
-
-package org.eclipse.tracecompass.analysis.timing.core.tests.segmentstore.statistics;
-
-import java.util.Collection;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.segmentstore.core.ISegment;
-
-/**
- * This calculates the statistics of a segment store in an offline manner to
- * validate online calculations.
- *
- * @author Matthew Khouzam
- *
- */
-public class OfflineStatisticsCalculator {
-    private final Collection<@NonNull ISegment> fSs;
-
-    /**
-     * Constructor
-     *
-     * @param ss
-     *            segment store, fully build
-     */
-    public OfflineStatisticsCalculator(Collection<@NonNull ISegment> ss) {
-        fSs = ss;
-    }
-
-    /**
-     * Get the max value
-     *
-     * @return the max value
-     */
-    public long getMax() {
-        long max = Long.MIN_VALUE;
-        for (ISegment interval : fSs) {
-            max = Math.max(max, interval.getLength());
-        }
-        return max;
-    }
-
-    /**
-     * Get the min value
-     *
-     * @return the min value
-     */
-    public long getMin() {
-        long min = Long.MAX_VALUE;
-        for (ISegment interval : fSs) {
-            min = Math.min(min, interval.getLength());
-        }
-        return min;
-    }
-
-    /**
-     * Get the average value
-     *
-     * @return the average value
-     */
-    public double getAvg() {
-        double total = 0;
-        for (ISegment interval : fSs) {
-            total += (double) interval.getLength() / (double) fSs.size();
-        }
-        return total;
-    }
-
-    /**
-     * Get the standard deviation.
-     *
-     * @return the standard deviation
-     */
-    public double getStdDev() {
-        if (fSs.size() < 3) {
-            return Double.NaN;
-        }
-        double mean = getAvg();
-
-        double totalVariance = 0;
-        for (ISegment interval : fSs) {
-            double result = interval.getLength() - mean;
-            totalVariance += result * result / (fSs.size() - 1);
-        }
-        return Math.sqrt(totalVariance);
-    }
-
-    /**
-     * Get the total
-     *
-     * @return the total
-     */
-    public long getTotal() {
-        long total = 0;
-        for (ISegment interval : fSs) {
-            total += interval.getLength();
-        }
-        return total;
-    }
-
-    /**
-     * Get the # of intervals
-     * @return the # of intervals
-     */
-    public int count() {
-        return fSs.size();
-    }
-}
index 3735830a9b2f8a8db918f1a9339cb4f930a072f9..e3ac1efcf76b3850a4c6d942b535171d78c5c939 100644 (file)
 
 package org.eclipse.tracecompass.analysis.timing.core.tests.segmentstore.statistics;
 
-import static org.junit.Assert.assertEquals;
-
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Collection;
 import java.util.Random;
+import java.util.stream.Collectors;
 
 import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.SegmentStoreStatistics;
+import org.eclipse.tracecompass.analysis.timing.core.tests.statistics.AbstractStatisticsTest;
 import org.eclipse.tracecompass.segmentstore.core.BasicSegment;
 import org.eclipse.tracecompass.segmentstore.core.ISegment;
-import org.junit.Test;
 
 /**
- * Test the segment store statistics calculations. This is done with two tests.
- * <ol>
- * <li>test the values vs some sample points calculated by hand (sanity test)
- * </li>
- * <li>2- test exhaustively vs a reference implementation.</li>
- * </ol>
+ * Test statistics for segment length
  *
  * @author Matthew Khouzam
  */
-public class SegmentStoreStatisticsTest {
-
-    private static final int MEDIUM_AMOUNT_OF_SEGMENTS = 100;
-    private static final int LARGE_AMOUNT_OF_SEGMENTS = 1000000;
-
-    private static final double NO_ERROR = 0.0;
-    private static final double ERROR = 0.000001;
-    private static final double APPROX_ERROR = 0.0001;
-
-    private static void testOnlineVsOffline(List<@NonNull ISegment> fixture) {
-        validate(new OfflineStatisticsCalculator(fixture), getSegStoreStat(fixture));
-    }
-
-    /**
-     * Test incrementing
-     */
-    @Test
-    public void climbTest() {
-        List<@NonNull ISegment> fixture = new ArrayList<>(MEDIUM_AMOUNT_OF_SEGMENTS);
-        for (int i = 0; i < MEDIUM_AMOUNT_OF_SEGMENTS; i++) {
-            fixture.add(createDummySegment(i, i * 2));
-        }
-        SegmentStoreStatistics sss = getSegStoreStat(fixture);
-        assertEquals("Average", 49.5, sss.getAverage(), ERROR);
-        assertEquals("Min", 0, sss.getMin());
-        assertEquals("Max", 99, sss.getMax());
-        assertEquals("Standard Deviation", 29.0, sss.getStdDev(), 0.02);
-        assertEquals("Min Segment", 0, sss.getMinSegment().getLength());
-        assertEquals("Max Segment", 99, sss.getMaxSegment().getLength());
-        testOnlineVsOffline(fixture);
-    }
-
-    private static SegmentStoreStatistics getSegStoreStat(List<@NonNull ISegment> fixture) {
-        SegmentStoreStatistics sss = new SegmentStoreStatistics();
-        for (ISegment seg : fixture) {
-            sss.update(seg);
-        }
-        return sss;
-    }
-
-    /**
-     * Test with segments of decrementing size
-     */
-    @Test
-    public void decrementingTest() {
-        List<@NonNull ISegment> fixture = new ArrayList<>(MEDIUM_AMOUNT_OF_SEGMENTS);
-        for (int i = MEDIUM_AMOUNT_OF_SEGMENTS; i >= 0; i--) {
-            fixture.add(createDummySegment(i, i * 2));
-        }
-        SegmentStoreStatistics sss = getSegStoreStat(fixture);
-        assertEquals("Average", 50, sss.getAverage(), NO_ERROR);
-        assertEquals("Min", 0, sss.getMin());
-        assertEquals("Max", 100, sss.getMax());
-        assertEquals("Standard Deviation", 29.3, sss.getStdDev(), 0.01);
-        assertEquals("Min Segment", 0, sss.getMinSegment().getLength());
-        assertEquals("Max Segment", 100, sss.getMaxSegment().getLength());
-        testOnlineVsOffline(fixture);
-    }
-
-    /**
-     * Test a data set with a small number of segments
-     */
-    @Test
-    public void smallTest() {
-        List<@NonNull ISegment> fixture = new ArrayList<>();
-        for (int i = 1; i >= 0; i--) {
-            fixture.add(createDummySegment(i, i * 2));
-        }
-        testOnlineVsOffline(fixture);
-    }
-
-    /**
-     * Test a data set with a large number of segments
-     */
-    @Test
-    public void largeTest() {
-        List<@NonNull ISegment> fixture = new ArrayList<>(LARGE_AMOUNT_OF_SEGMENTS);
-        for (int i = 1; i <= LARGE_AMOUNT_OF_SEGMENTS; i++) {
-            fixture.add(createDummySegment(i, i * 2));
-        }
-        testOnlineVsOffline(fixture);
-    }
-
-    /**
-     * Test a random dataset where the distribution follows white noise
-     */
-    @Test
-    public void noiseTest() {
-        Random rnd = new Random();
-        rnd.setSeed(1234);
-        List<@NonNull ISegment> fixture = new ArrayList<>(LARGE_AMOUNT_OF_SEGMENTS);
-        for (int i = 1; i <= LARGE_AMOUNT_OF_SEGMENTS; i++) {
-            int start = Math.abs(rnd.nextInt(100000000));
-            int end = start + Math.abs(rnd.nextInt(1000000));
-            fixture.add(createDummySegment(start, end));
-        }
-        testOnlineVsOffline(fixture);
-    }
-
-    /**
-     * Test a random dataset where the distribution follows gaussian noise
-     */
-    @Test
-    public void gaussianNoiseTest() {
-        Random rnd = new Random();
-        rnd.setSeed(1234);
-        List<@NonNull ISegment> fixture = new ArrayList<>(LARGE_AMOUNT_OF_SEGMENTS);
-        for (int i = 1; i <= LARGE_AMOUNT_OF_SEGMENTS; i++) {
-            int start = Math.abs(rnd.nextInt(100000000));
-            final int delta = Math.abs(rnd.nextInt(1000));
-            int end = start + delta * delta;
-            fixture.add(createDummySegment(start, end));
-        }
-        testOnlineVsOffline(fixture);
-    }
+public class SegmentStoreStatisticsTest extends AbstractStatisticsTest<@NonNull ISegment> {
 
-    /**
-     * Test building a statistics store with streams
-     */
-    @Test
-    public void streamBuildingTest() {
-        SegmentStoreStatistics expected = new SegmentStoreStatistics();
-        List<@NonNull ISegment> fixture = new ArrayList<>(LARGE_AMOUNT_OF_SEGMENTS);
-        for (long i = 0; i < LARGE_AMOUNT_OF_SEGMENTS; i++) {
-            fixture.add(new BasicSegment(i, i + 2));
-        }
-        fixture.forEach(e -> expected.update(e));
-        SegmentStoreStatistics actual = fixture.stream()
-                .<@NonNull SegmentStoreStatistics> collect(SegmentStoreStatistics::new, SegmentStoreStatistics::update, SegmentStoreStatistics::merge);
-        validate(expected, actual);
-    }
+    private final Random fRandom = new Random(10);
 
     /**
-     * Test building a statistics store with parallel streams
+     * Constructor
      */
-    @Test
-    public void parallelStreamBuildingTest() {
-        SegmentStoreStatistics expected = new SegmentStoreStatistics();
-        List<@NonNull ISegment> fixture = new ArrayList<>(LARGE_AMOUNT_OF_SEGMENTS);
-        for (long i = 0; i < LARGE_AMOUNT_OF_SEGMENTS; i++) {
-            fixture.add(new BasicSegment(i, i + 2));
-        }
-        fixture.forEach(e -> expected.update(e));
-        SegmentStoreStatistics actual = fixture.parallelStream()
-                .<@NonNull SegmentStoreStatistics> collect(SegmentStoreStatistics::new, SegmentStoreStatistics::update, SegmentStoreStatistics::merge);
-        validate(expected, actual);
+    public SegmentStoreStatisticsTest() {
+        super(s -> s.getLength());
     }
 
-    /**
-     * Test statistics nodes being merged. Two contiguous blocks.
-     */
-    @Test
-    public void mergeStatisticsNodesTest() {
-        // calculates stats for all the segments
-        SegmentStoreStatistics expected = new SegmentStoreStatistics();
-        // calculates stats for half of the segments
-        SegmentStoreStatistics a = new SegmentStoreStatistics();
-        // calculates stats for another half of the segments
-        SegmentStoreStatistics b = new SegmentStoreStatistics();
-        List<@NonNull ISegment> fixture = new ArrayList<>();
-        for (int i = 0; i < 10; i++) {
-            ISegment seg = new BasicSegment(i, i * 2 + 2);
-            expected.update(seg);
-            a.update(seg);
-            fixture.add(seg);
-        }
-        for (int i = 0; i < 10; i++) {
-            ISegment seg = new BasicSegment(i, i * 2 + 2);
-            expected.update(seg);
-            b.update(seg);
-            fixture.add(seg);
-        }
-        a.merge(b);
-        OfflineStatisticsCalculator offlineExpected = new OfflineStatisticsCalculator(fixture);
-        // Compare the expected stats with the offline algorithm
-        validate(offlineExpected, expected);
-        // Compare the results of the merge with the expected results
-        validate(expected, a);
-    }
+    @Override
+    protected Collection<@NonNull ISegment> createElementsWithValues(Collection<@NonNull Long> longFixture) {
+        return longFixture.stream()
+                .map(l -> {
+                    long nextStart = fRandom.nextInt(10000000);
+                    long nextEnd = nextStart + l;
+                    // Check the boundaries, it is random after all, so if
+                    // there's an overflow, just take the max value as end time
+                    if (nextEnd < nextStart) {
+                        nextEnd = Long.MAX_VALUE;
+                        nextStart = nextEnd - l;
+                    }
+                    return new BasicSegment(nextStart, nextEnd);
+                })
+                .collect(Collectors.toList());
 
-    /**
-     * Test statistics nodes being merged. Two random blocks.
-     */
-    @Test
-    public void mergeStatisticsRandomNodesTest() {
-        // calculates stats for all the segments
-        SegmentStoreStatistics expected = new SegmentStoreStatistics();
-        // calculates stats for half of the segments, randomly
-        SegmentStoreStatistics a = new SegmentStoreStatistics();
-        // calculates stats for the other half of the segments
-        SegmentStoreStatistics b = new SegmentStoreStatistics();
-        List<@NonNull ISegment> fixture = new ArrayList<>();
-        Random rnd = new Random();
-        rnd.setSeed(10);
-        int size = rnd.nextInt(1000);
-        int size2 = rnd.nextInt(1000);
-        for (int i = 0; i < size; i++) {
-            int start = Math.abs(rnd.nextInt(100000000));
-            final int delta = Math.abs(rnd.nextInt(1000));
-            int end = start + delta * delta;
-            ISegment seg = new BasicSegment(start, end);
-            expected.update(seg);
-            a.update(seg);
-            fixture.add(seg);
-        }
-        for (int i = 0; i < size2; i++) {
-            int start = Math.abs(rnd.nextInt(100000000));
-            final int delta = Math.abs(rnd.nextInt(1000));
-            int end = start + delta * delta;
-            ISegment seg = new BasicSegment(start, end);
-            expected.update(seg);
-            b.update(seg);
-            fixture.add(seg);
-        }
-        a.merge(b);
-        assertEquals(size + size2, a.getNbSegments());
-        OfflineStatisticsCalculator offlineExpected = new OfflineStatisticsCalculator(fixture);
-        // Compare the expected stats with the offline algorithm
-        validate(offlineExpected, expected);
-        // Compare the results of the merge with the expected results
-        validate(expected, a);
     }
 
-    /**
-     * Test statistics nodes being merged. Two overlapping blocks.
-     */
-    @Test
-    public void mergeStatisticsOverlappingNodesTest() {
-        // calculates stats for all the segments
-        SegmentStoreStatistics expected = new SegmentStoreStatistics();
-        // calculates stats for half of the segments
-        SegmentStoreStatistics a = new SegmentStoreStatistics();
-        // calculates stats for the other half of the segments
-        SegmentStoreStatistics b = new SegmentStoreStatistics();
-        List<@NonNull ISegment> fixture = new ArrayList<>();
-        for (int i = 0; i < 100; i++) {
-            BasicSegment seg = new BasicSegment(i, i * 2 + 2);
-            expected.update(seg);
-            if ((i & 2) != 0) {
-                a.update(seg);
-            } else {
-                b.update(seg);
-            }
-            fixture.add(seg);
-        }
-        a.merge(b);
-        OfflineStatisticsCalculator offlineExpected = new OfflineStatisticsCalculator(fixture);
-        validate(offlineExpected, expected);
-        validate(expected, a);
+    @Override
+    public void testLimitDataset2() {
+        /* ISegments do not support negative values */
     }
 
-    private static @NonNull SegmentStoreStatistics fillSmallStatistics() {
-        SegmentStoreStatistics stats = new SegmentStoreStatistics();
-        for (int i = 0; i < 10; i++) {
-            BasicSegment seg = new BasicSegment(i, i * 2 + 2);
-            stats.update(seg);
-        }
-        return stats;
+    @Override
+    public void testLargeDatasetNegative() {
+        /* ISegments do not support negative values */
     }
 
-    /**
-     * Test corner cases when merging statistics nodes
-     */
-    @Test
-    public void mergeStatisticsCornerCaseNodesTest() {
-        ISegment segment = new BasicSegment(1, 5);
-
-        // Control statistics, not to be modified
-        SegmentStoreStatistics noSegments = new SegmentStoreStatistics();
-        SegmentStoreStatistics oneSegment = new SegmentStoreStatistics();
-        oneSegment.update(segment);
-
-        // The segment store statistics to test
-        SegmentStoreStatistics testStats = new SegmentStoreStatistics();
-        SegmentStoreStatistics testStats2 = new SegmentStoreStatistics();
-
-        // Test merging empty stats on a non-empty one
-        testStats.update(segment);
-        testStats.merge(testStats2);
-        validate(oneSegment, testStats);
-        validate(noSegments, testStats2);
-
-        // Test merging on an empty stats
-        testStats2.merge(testStats);
-        validate(oneSegment, testStats);
-        validate(oneSegment, testStats2);
-
-        // Fill a small segment store and add the one extra segment to it
-        SegmentStoreStatistics expected = fillSmallStatistics();
-        expected.update(segment);
-
-        // Test merging stats with only 1 segment
-        testStats = fillSmallStatistics();
-        testStats.merge(testStats2);
-        validate(oneSegment, testStats2);
-        validate(expected, testStats);
-
-        // Test merging on stats with only 1 segment
-        testStats = fillSmallStatistics();
-        testStats2.merge(testStats);
-        validate(fillSmallStatistics(), testStats);
-        validate(expected, testStats2);
-
-    }
-
-    private static void validate(SegmentStoreStatistics expected, SegmentStoreStatistics toBeTested) {
-        assertEquals("# of Segments", expected.getNbSegments(), toBeTested.getNbSegments());
-        assertEquals("Total duration", expected.getTotal(), toBeTested.getTotal(), ERROR * expected.getTotal());
-        assertEquals("Average", expected.getAverage(), toBeTested.getAverage(), ERROR * expected.getAverage());
-        assertEquals("Min", expected.getMin(), toBeTested.getMin());
-        assertEquals("Max", expected.getMax(), toBeTested.getMax());
-        assertEquals("Min Segment", expected.getMinSegment().getLength(), toBeTested.getMinSegment().getLength());
-        assertEquals("Max Segment", expected.getMaxSegment().getLength(), toBeTested.getMaxSegment().getLength());
-        assertEquals("Standard Deviation", expected.getStdDev(), toBeTested.getStdDev(), APPROX_ERROR * expected.getStdDev());
-    }
-
-    private static void validate(OfflineStatisticsCalculator osc, SegmentStoreStatistics sss) {
-        assertEquals("# of Segments", osc.count(), sss.getNbSegments());
-        assertEquals("Total duration", osc.getTotal(), sss.getTotal(), ERROR * osc.getTotal());
-        assertEquals("Average", osc.getAvg(), sss.getAverage(), ERROR * osc.getAvg());
-        assertEquals("Min", osc.getMin(), sss.getMin());
-        assertEquals("Max", osc.getMax(), sss.getMax());
-        assertEquals("Min Segment", osc.getMin(), sss.getMinSegment().getLength());
-        assertEquals("Max Segment", osc.getMax(), sss.getMaxSegment().getLength());
-        assertEquals("Standard Deviation", osc.getStdDev(), sss.getStdDev(), ERROR * osc.getStdDev());
-    }
-
-    private static @NonNull BasicSegment createDummySegment(int start, int end) {
-        return new BasicSegment(start, end);
-    }
 }
index f829e6688d32ae3b00e1a644ff56ae3175e953b4..486230fa6d2eaef06157c8989de2f359841918e2 100644 (file)
@@ -12,11 +12,15 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.function.Function;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.tracecompass.analysis.timing.core.segmentstore.ISegmentStoreProvider;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.Statistics;
 import org.eclipse.tracecompass.segmentstore.core.ISegment;
 import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
 import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
@@ -34,11 +38,13 @@ import com.google.common.collect.ImmutableList;
  */
 public abstract class AbstractSegmentStatisticsAnalysis extends TmfAbstractAnalysisModule {
 
+    private static Function<ISegment, Long> FCT_LENGTH = s -> s.getLength();
+
     private @Nullable ISegmentStoreProvider fSegmentStoreProviderModule;
 
-    private @Nullable SegmentStoreStatistics fTotalStats;
+    private @Nullable IStatistics<ISegment> fTotalStats;
 
-    private Map<String, SegmentStoreStatistics> fPerSegmentTypeStats = new HashMap<>();
+    private Map<String, IStatistics<ISegment>> fPerSegmentTypeStats = new HashMap<>();
 
     @Override
     protected Iterable<IAnalysisModule> getDependentAnalyses() {
@@ -59,21 +65,19 @@ public abstract class AbstractSegmentStatisticsAnalysis extends TmfAbstractAnaly
             return false;
         }
 
-        SegmentStoreStatistics totalStats = getTotalStats(TmfTimeRange.ETERNITY.getStartTime().toNanos(), TmfTimeRange.ETERNITY.getEndTime().toNanos(), monitor);
+        IStatistics<ISegment> totalStats = getTotalStats(TmfTimeRange.ETERNITY.getStartTime().toNanos(), TmfTimeRange.ETERNITY.getEndTime().toNanos(), monitor);
         if (totalStats == null) {
             return false;
         }
 
-        Map<@NonNull String, @NonNull SegmentStoreStatistics> perTypeStats = getPerTypeStats(TmfTimeRange.ETERNITY.getStartTime().toNanos(), TmfTimeRange.ETERNITY.getEndTime().toNanos(), monitor);
-        if (perTypeStats == null) {
-            return false;
-        }
+        Map<String, IStatistics<ISegment>> perTypeStats = getPerTypeStats(TmfTimeRange.ETERNITY.getStartTime().toNanos(), TmfTimeRange.ETERNITY.getEndTime().toNanos(), monitor);
         fTotalStats = totalStats;
         fPerSegmentTypeStats = perTypeStats;
+
         return true;
     }
 
-    private @Nullable SegmentStoreStatistics getTotalStats(long start, long end, IProgressMonitor monitor) {
+    private @Nullable IStatistics<ISegment> getTotalStats(long start, long end, IProgressMonitor monitor) {
         Iterable<@NonNull ISegment> store = getSegmentStore(start, end);
         if (store == null) {
             return null;
@@ -99,19 +103,42 @@ public abstract class AbstractSegmentStatisticsAnalysis extends TmfAbstractAnaly
      * @return The total statistics, or null if segment store is not valid or if
      *         the request is canceled
      * @since 1.2
+     * @deprecated use {@link #getStatsForRange(long, long, IProgressMonitor)} instead
      */
+    @Deprecated
     public @Nullable SegmentStoreStatistics getTotalStatsForRange(long start, long end, IProgressMonitor monitor) {
+        IStatistics<@NonNull ISegment> stats = getStatsForRange(start, end, monitor);
+        return (stats == null) ? null : new SegmentStoreStatistics(stats);
+    }
+
+    /**
+     * Get the total statistics for a specific range. If the range start is
+     * TmfTimeRange.ETERNITY.getStartTime().toNanos() and the range end is
+     * TmfTimeRange.ETERNITY.getEndTime().toNanos(), it will return the
+     * statistics for the whole trace.
+     *
+     * @param start
+     *            The start time of the range
+     * @param end
+     *            The end time of the range
+     * @param monitor
+     *            The progress monitor
+     * @return The total statistics, or null if segment store is not valid or if
+     *         the request is canceled
+     * @since 1.3
+     */
+    public @Nullable IStatistics<ISegment> getStatsForRange(long start, long end, IProgressMonitor monitor) {
         ITmfTrace trace = getTrace();
         if (trace != null && (start == TmfTimeRange.ETERNITY.getStartTime().toNanos() && end == TmfTimeRange.ETERNITY.getEndTime().toNanos())) {
             waitForCompletion();
-            return getTotalStats();
+            return getStatsTotal();
         }
         return getTotalStats(start, end, monitor);
     }
 
-    private @Nullable Map<@NonNull String, @NonNull SegmentStoreStatistics> getPerTypeStats(long start, long end, IProgressMonitor monitor) {
+    private Map<@NonNull String, org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics<ISegment>> getPerTypeStats(long start, long end, IProgressMonitor monitor) {
         Iterable<@NonNull ISegment> store = getSegmentStore(start, end);
-        if (monitor.isCanceled()) {
+        if (monitor.isCanceled() || store == null) {
             return Collections.EMPTY_MAP;
         }
         return calculateTotalPerType(store, monitor);
@@ -132,12 +159,39 @@ public abstract class AbstractSegmentStatisticsAnalysis extends TmfAbstractAnaly
      * @return The per segment type statistics, or null if segment store is not
      *         valid or if the request is canceled
      * @since 1.2
+     * @deprecated use {@link #getStatsPerTypeForRange(long, long, IProgressMonitor)} instead
      */
-    public @Nullable Map<@NonNull String, @NonNull SegmentStoreStatistics> getPerSegmentTypeStatsForRange(long start, long end, IProgressMonitor monitor) {
+    @Deprecated
+    public @Nullable Map<String, SegmentStoreStatistics> getPerSegmentTypeStatsForRange(long start, long end, IProgressMonitor monitor) {
+        Map<String, IStatistics<ISegment>> stats = getStatsPerTypeForRange(start, end, monitor);
+        Map<String, SegmentStoreStatistics> map = new HashMap<>();
+        for (Entry<String, IStatistics<ISegment>> entry : stats.entrySet()) {
+            map.put(entry.getKey(), new SegmentStoreStatistics(entry.getValue()));
+        }
+        return map;
+    }
+
+    /**
+     * Get the per segment type statistics for a specific range. If the range
+     * start is TmfTimeRange.ETERNITY.getStartTime().toNanos() and the range end
+     * is TmfTimeRange.ETERNITY.getEndTime().toNanos(), it will return the
+     * statistics for the whole trace.
+     *
+     * @param start
+     *            The start time of the range
+     * @param end
+     *            The end time of the range
+     * @param monitor
+     *            The progress monitor
+     * @return The per segment type statistics, or null if segment store is not
+     *         valid or if the request is canceled
+     * @since 1.3
+     */
+    public Map<@NonNull String, org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics<ISegment>> getStatsPerTypeForRange(long start, long end, IProgressMonitor monitor) {
         ITmfTrace trace = getTrace();
         if (trace != null && (start == TmfTimeRange.ETERNITY.getStartTime().toNanos() && end == TmfTimeRange.ETERNITY.getEndTime().toNanos())) {
             waitForCompletion();
-            return getPerSegmentTypeStats();
+            return getStatsPerType();
         }
         return getPerTypeStats(start, end, monitor);
     }
@@ -161,8 +215,8 @@ public abstract class AbstractSegmentStatisticsAnalysis extends TmfAbstractAnaly
                 : Collections.EMPTY_LIST;
     }
 
-    private static @Nullable SegmentStoreStatistics calculateTotalManual(Iterable<@NonNull ISegment> segments, IProgressMonitor monitor) {
-        SegmentStoreStatistics total = new SegmentStoreStatistics();
+    private static @Nullable IStatistics<ISegment> calculateTotalManual(Iterable<@NonNull ISegment> segments, IProgressMonitor monitor) {
+        IStatistics<ISegment> total = new Statistics<>(FCT_LENGTH);
         Iterator<@NonNull ISegment> iter = segments.iterator();
         while (iter.hasNext()) {
             if (monitor.isCanceled()) {
@@ -174,8 +228,8 @@ public abstract class AbstractSegmentStatisticsAnalysis extends TmfAbstractAnaly
         return total;
     }
 
-    private Map<@NonNull String, @NonNull SegmentStoreStatistics> calculateTotalPerType(Iterable<ISegment> segments, IProgressMonitor monitor) {
-        Map<String, SegmentStoreStatistics> perSegmentTypeStats = new HashMap<>();
+    private Map<@NonNull String, org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics<ISegment>> calculateTotalPerType(Iterable<ISegment> segments, IProgressMonitor monitor) {
+        Map<String, IStatistics<ISegment>> perSegmentTypeStats = new HashMap<>();
 
         Iterator<ISegment> iter = segments.iterator();
         while (iter.hasNext()) {
@@ -185,9 +239,9 @@ public abstract class AbstractSegmentStatisticsAnalysis extends TmfAbstractAnaly
             ISegment segment = iter.next();
             String segmentType = getSegmentType(segment);
             if (segmentType != null) {
-                SegmentStoreStatistics values = perSegmentTypeStats.get(segmentType);
+                IStatistics<ISegment> values = perSegmentTypeStats.get(segmentType);
                 if (values == null) {
-                    values = new SegmentStoreStatistics();
+                    values = new Statistics<>(FCT_LENGTH);
                 }
                 values.update(segment);
                 perSegmentTypeStats.put(segmentType, values);
@@ -224,8 +278,21 @@ public abstract class AbstractSegmentStatisticsAnalysis extends TmfAbstractAnaly
      * The total statistics
      *
      * @return the total statistics
+     * @deprecated use {@link #getStatsTotal()} instead
      */
+    @Deprecated
     public @Nullable SegmentStoreStatistics getTotalStats() {
+        IStatistics<@NonNull ISegment> totalStats = fTotalStats;
+        return totalStats == null ? null : new SegmentStoreStatistics(totalStats);
+    }
+
+    /**
+     * Get the statistics for the full segment store
+     *
+     * @return The complete statistics
+     * @since 1.3
+     */
+    public @Nullable IStatistics<ISegment> getStatsTotal() {
         return fTotalStats;
     }
 
@@ -233,8 +300,24 @@ public abstract class AbstractSegmentStatisticsAnalysis extends TmfAbstractAnaly
      * The per syscall statistics
      *
      * @return the per syscall statistics
+     * @deprecated use {@link #getStatsPerType()} instead
      */
+    @Deprecated
     public @Nullable Map<String, SegmentStoreStatistics> getPerSegmentTypeStats() {
+        Map<String, SegmentStoreStatistics> map = new HashMap<>();
+        for (Entry<String, IStatistics<ISegment>> entry : fPerSegmentTypeStats.entrySet()) {
+            map.put(entry.getKey(), new SegmentStoreStatistics(entry.getValue()));
+        }
+        return map;
+    }
+
+    /**
+     * Get the statistics for each type of segment in this segment store
+     *
+     * @return the map of statistics per type
+     * @since 1.3
+     */
+    public Map<String, IStatistics<ISegment>> getStatsPerType() {
         return fPerSegmentTypeStats;
     }
 
index 23ce5f65f986db349d9273eb6ba15fa7c19c435d..b3d6a0400f76a557cd465e70c401da1379f676f6 100644 (file)
@@ -11,6 +11,8 @@
  *******************************************************************************/
 package org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics;
 
+import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.Statistics;
 import org.eclipse.tracecompass.segmentstore.core.BasicSegment;
 import org.eclipse.tracecompass.segmentstore.core.ISegment;
 
@@ -20,35 +22,37 @@ import org.eclipse.tracecompass.segmentstore.core.ISegment;
  * @author Bernd Hufmann
  */
 public class SegmentStoreStatistics {
-    private ISegment fMin;
-    private ISegment fMax;
-    private long fNbSegments;
-    private double fAverage;
+
+    private static final ISegment MIN_SEGMENT = new BasicSegment(0, Long.MAX_VALUE);
+    private static final ISegment MAX_SEGMENT = new BasicSegment(Long.MIN_VALUE, 0);
+
+    private final IStatistics<ISegment> fStatistics;
+
     /**
-     * reminder, this is the variance * nb elem, as per the online algorithm
+     * Constructor
      */
-    private double fVariance;
-    private double fTotal;
+    public SegmentStoreStatistics() {
+        fStatistics = new Statistics<>(s -> s.getLength());
+    }
 
     /**
      * Constructor
+     *
+     * @param stats The statistics object
+     * @since 1.3
      */
-    public SegmentStoreStatistics() {
-        fMin = new BasicSegment(0, Long.MAX_VALUE);
-        fMax = new BasicSegment(Long.MIN_VALUE, 0);
-        fNbSegments = 0;
-        fAverage = 0.0;
-        fVariance = 0.0;
-        fTotal = 0.0;
+    public SegmentStoreStatistics(IStatistics<ISegment> stats) {
+        fStatistics = stats;
     }
 
     /**
      * Get minimum value
      *
      * @return minimum value
+     * @since 1.2
      */
     public long getMin() {
-        return fMin.getLength();
+        return fStatistics.getMin();
     }
 
     /**
@@ -57,7 +61,7 @@ public class SegmentStoreStatistics {
      * @return maximum value
      */
     public long getMax() {
-        return fMax.getLength();
+        return fStatistics.getMax();
     }
 
     /**
@@ -66,7 +70,8 @@ public class SegmentStoreStatistics {
      * @return segment with minimum length
      */
     public ISegment getMinSegment() {
-        return fMin;
+        ISegment minObject = fStatistics.getMinObject();
+        return minObject == null ? MIN_SEGMENT : minObject;
     }
 
     /**
@@ -75,7 +80,8 @@ public class SegmentStoreStatistics {
      * @return segment with maximum length
      */
     public ISegment getMaxSegment() {
-        return fMax;
+        ISegment maxObject = fStatistics.getMaxObject();
+        return maxObject == null ? MAX_SEGMENT : maxObject;
     }
 
     /**
@@ -84,7 +90,7 @@ public class SegmentStoreStatistics {
      * @return number of segments analyzed
      */
     public long getNbSegments() {
-        return fNbSegments;
+        return fStatistics.getNbElements();
     }
 
     /**
@@ -93,7 +99,7 @@ public class SegmentStoreStatistics {
      * @return arithmetic average
      */
     public double getAverage() {
-        return fAverage;
+        return fStatistics.getMean();
     }
 
     /**
@@ -106,7 +112,7 @@ public class SegmentStoreStatistics {
      *         there are less than 3 elements
      */
     public double getStdDev() {
-        return fNbSegments > 2 ? Math.sqrt(fVariance / (fNbSegments - 1)) : Double.NaN;
+        return fStatistics.getStdDev();
     }
 
     /**
@@ -116,7 +122,7 @@ public class SegmentStoreStatistics {
      * @since 1.1
      */
     public double getTotal() {
-        return fTotal;
+        return fStatistics.getTotal();
     }
 
     /**
@@ -128,23 +134,7 @@ public class SegmentStoreStatistics {
      *            the segment used for the update
      */
     public void update(ISegment segment) {
-        long value = segment.getLength();
-        /*
-         * Min and max are trivial, as well as number of segments
-         */
-        long min = fMin.getLength();
-        long max = fMax.getLength();
-        fMin = min <= value ? fMin : segment;
-        fMax = max >= value ? fMax : segment;
-
-        fNbSegments++;
-        /*
-         * The running mean is not trivial, see proof in javadoc.
-         */
-        double delta = value - fAverage;
-        fAverage += delta / fNbSegments;
-        fVariance += delta * (value - fAverage);
-        fTotal += value;
+        fStatistics.update(segment);
     }
 
     /**
@@ -157,70 +147,11 @@ public class SegmentStoreStatistics {
      * @since 1.2
      */
     public void merge(SegmentStoreStatistics other) {
-        if (other.fNbSegments == 0) {
-            return;
-        } else if (fNbSegments == 0) {
-            copy(other);
-        } else if (other.fNbSegments == 1) {
-            update(other.fMax);
-        } else if (fNbSegments == 1) {
-            SegmentStoreStatistics copyOther = new SegmentStoreStatistics();
-            copyOther.copy(other);
-            copyOther.update(fMax);
-            copy(copyOther);
-        } else {
-            internalMerge(other);
-        }
+        fStatistics.merge(other.getStatObject());
     }
 
-    private void internalMerge(SegmentStoreStatistics other) {
-        /*
-         * Min and max are trivial, as well as number of segments
-         */
-        long min = fMin.getLength();
-        long max = fMax.getLength();
-        fMin = min <= other.getMin() ? fMin : other.getMinSegment();
-        fMax = max >= other.getMax() ? fMax : other.getMaxSegment();
-
-        long oldNbSeg = fNbSegments;
-        double oldAverage = fAverage;
-        long otherSegments = other.getNbSegments();
-        double otherAverage = other.getAverage();
-        fNbSegments += otherSegments;
-        fTotal += other.getTotal();
-
-        /*
-         * Average is a weighted average
-         */
-        fAverage = ((oldNbSeg * oldAverage) + (otherAverage * otherSegments)) / fNbSegments;
-
-        /*
-         * This one is a bit tricky.
-         *
-         * The variance is the sum of the deltas from a mean squared.
-         *
-         * So if we add the old mean squared back to to variance and remove the
-         * new mean, the standard deviation can be easily calculated.
-         */
-        double avg1Sq = oldAverage * oldAverage;
-        double avg2sq = otherAverage * otherAverage;
-        double avgtSq = fAverage * fAverage;
-        /*
-         * This is a tricky part, bear in mind that the set is not continuous but discrete,
-         * Therefore, we have for n elements, n-1 intervals between them.
-         * Ergo, n-1 intervals are used for divisions and multiplications.
-         */
-        double variance1 = fVariance / (oldNbSeg - 1);
-        double variance2 = other.fVariance / (otherSegments - 1);
-        fVariance = ((variance1 + avg1Sq - avgtSq) * (oldNbSeg - 1) + (variance2 + avg2sq - avgtSq) * (otherSegments - 1));
+    private IStatistics<ISegment> getStatObject() {
+        return fStatistics;
     }
 
-    private void copy(SegmentStoreStatistics copyOther) {
-        fAverage = copyOther.fAverage;
-        fMax = copyOther.fMax;
-        fMin = copyOther.fMin;
-        fNbSegments = copyOther.fNbSegments;
-        fTotal = copyOther.fTotal;
-        fVariance = copyOther.fVariance;
-    }
 }
index 33c9d084cb6f8966e1d713575bb172dfcfa03c1c..5fed50a44e3970e16fbb698f003ad7dfd974d680 100644 (file)
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-Vendor: %Bundle-Vendor
-Bundle-Version: 1.2.0.qualifier
+Bundle-Version: 1.3.0.qualifier
 Bundle-Localization: plugin
 Bundle-SymbolicName: org.eclipse.tracecompass.analysis.timing.ui;singleton:=true
 Bundle-Activator: org.eclipse.tracecompass.internal.analysis.timing.ui.Activator
index 0a18e3977a095ec291126b2530e7a1b1be4afc5f..2a019752fcdc192787c226effd2306b1f4715ab6 100644 (file)
@@ -35,8 +35,9 @@ import com.google.common.base.Joiner;
  * Abstract view to to be extended to display segment store statistics.
  *
  * @author Bernd Hufmann
- *
+ * @deprecated use {@link AbstractSegmentsStatisticsView} instead
  */
+@Deprecated
 public abstract class AbstractSegmentStoreStatisticsView extends TmfView {
 
     private final Action fExportAction = new ExportToTsvAction() {
index b6b288620d28354de95df734289be513cf4327ee..c27f7ecd98041b584e6553390b68400114026be3 100644 (file)
@@ -59,8 +59,9 @@ import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeViewerEntry;
  * statistics
  *
  * @author Bernd Hufmann
- *
+ * @deprecated use {@link AbstractSegmentsStatisticsViewer} instead
  */
+@Deprecated
 public abstract class AbstractSegmentStoreStatisticsViewer extends AbstractTmfTreeViewer {
 
     private static final Format FORMATTER = new SubSecondTimeWithUnitFormat();
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentsStatisticsView.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentsStatisticsView.java
new file mode 100644 (file)
index 0000000..edf8bd3
--- /dev/null
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2017 Ericsson, École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics;
+
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.action.Action;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.ExportToTsvAction;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
+import org.eclipse.tracecompass.tmf.ui.views.TmfView;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+
+/**
+ * Abstract view to to be extended to display segment store statistics.
+ *
+ * @author Bernd Hufmann
+ * @author Geneviève Bastien
+ * @since 1.3
+ */
+public abstract class AbstractSegmentsStatisticsView extends TmfView {
+
+    private final Action fExportAction = new ExportToTsvAction() {
+        @Override
+        protected void exportToTsv(@Nullable OutputStream stream) {
+            AbstractSegmentsStatisticsView.this.exportToTsv(stream);
+        }
+
+        @Override
+        protected @Nullable Shell getShell() {
+            return getViewSite().getShell();
+        }
+
+    };
+
+    private @Nullable AbstractTmfTreeViewer fStatsViewer = null;
+
+    /**
+     * Constructor
+     */
+    public AbstractSegmentsStatisticsView() {
+        super("StatisticsView"); //$NON-NLS-1$
+    }
+
+    @Override
+    public void createPartControl(@Nullable Composite parent) {
+        super.createPartControl(parent);
+        AbstractTmfTreeViewer statsViewer = createSegmentStoreStatisticsViewer(NonNullUtils.checkNotNull(parent));
+        ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
+        if (trace != null) {
+            statsViewer.loadTrace(trace);
+        }
+        fStatsViewer = statsViewer;
+        getViewSite().getActionBars().getMenuManager().add(fExportAction);
+    }
+
+    @Override
+    public void setFocus() {
+        AbstractTmfTreeViewer statsViewer = fStatsViewer;
+        if (statsViewer != null) {
+            statsViewer.getControl().setFocus();
+        }
+    }
+
+    @Override
+    public void dispose() {
+        super.dispose();
+        AbstractTmfTreeViewer statsViewer = fStatsViewer;
+        if (statsViewer != null) {
+            statsViewer.dispose();
+        }
+    }
+
+    /**
+     * Creates a segment store statistics viewer instance.
+     *
+     * @param parent
+     *            the parent composite to create the viewer in.
+     * @return the latency statistics viewer implementation
+     */
+    protected abstract AbstractTmfTreeViewer createSegmentStoreStatisticsViewer(Composite parent);
+
+    /**
+     * Export a given items's TSV
+     *
+     * @param stream
+     *            an output stream to write the TSV to
+     * @since 1.2
+     */
+    @VisibleForTesting
+    protected void exportToTsv(@Nullable OutputStream stream) {
+        try (PrintWriter pw = new PrintWriter(stream)) {
+            AbstractTmfTreeViewer statsViewer = fStatsViewer;
+            if (statsViewer == null) {
+                return;
+            }
+            Tree tree = statsViewer.getTreeViewer().getTree();
+            int size = tree.getItemCount();
+            List<String> columns = new ArrayList<>();
+            for (int i = 0; i < tree.getColumnCount(); i++) {
+                String valueOf = String.valueOf(tree.getColumn(i).getText());
+                if (valueOf.isEmpty() && i == tree.getColumnCount() - 1) {
+                    // Linux "feature", an invisible column is added at the end
+                    // with gtk2
+                    break;
+                }
+                columns.add(valueOf);
+            }
+            String join = Joiner.on('\t').skipNulls().join(columns);
+            pw.println(join);
+            for (int i = 0; i < size; i++) {
+                TreeItem item = tree.getItem(i);
+                printItem(pw, columns, item);
+            }
+        }
+    }
+
+    private void printItem(PrintWriter pw, List<String> columns, @Nullable TreeItem item) {
+        if (item == null) {
+            return;
+        }
+        List<String> data = new ArrayList<>();
+        for (int col = 0; col < columns.size(); col++) {
+            data.add(String.valueOf(item.getText(col)));
+        }
+        pw.println(Joiner.on('\t').join(data));
+        for (TreeItem child : item.getItems()) {
+            printItem(pw, columns, child);
+        }
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentsStatisticsViewer.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentsStatisticsViewer.java
new file mode 100644 (file)
index 0000000..ff73a35
--- /dev/null
@@ -0,0 +1,500 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2017 Ericsson, École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.text.Format;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.AbstractSegmentStatisticsAnalysis;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.Statistics;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.SubSecondTimeWithUnitFormat;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.statistics.Messages;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeColumnDataProvider;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeViewerEntry;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeColumnData;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeViewerEntry;
+
+/**
+ * An abstract tree viewer implementation for displaying segment store
+ * statistics
+ *
+ * @author Bernd Hufmann
+ * @author Geneviève Bastien
+ * @since 1.3
+ */
+public abstract class AbstractSegmentsStatisticsViewer extends AbstractTmfTreeViewer {
+
+    private static final Format FORMATTER = new SubSecondTimeWithUnitFormat();
+
+    private @Nullable TmfAbstractAnalysisModule fModule;
+    private MenuManager fTablePopupMenuManager;
+
+    private static final String[] COLUMN_NAMES = new String[] {
+            checkNotNull(Messages.SegmentStoreStatistics_LevelLabel),
+            checkNotNull(Messages.SegmentStoreStatistics_Statistics_MinLabel),
+            checkNotNull(Messages.SegmentStoreStatistics_MaxLabel),
+            checkNotNull(Messages.SegmentStoreStatistics_AverageLabel),
+            checkNotNull(Messages.SegmentStoreStatisticsViewer_StandardDeviation),
+            checkNotNull(Messages.SegmentStoreStatisticsViewer_Count),
+            checkNotNull(Messages.SegmentStoreStatisticsViewer_Total)
+    };
+
+    /**
+     * Constructor
+     *
+     * @param parent
+     *            the parent composite
+     */
+    public AbstractSegmentsStatisticsViewer(Composite parent) {
+        super(parent, false);
+        setLabelProvider(new SegmentStoreStatisticsLabelProvider());
+        fTablePopupMenuManager = new MenuManager();
+        fTablePopupMenuManager.setRemoveAllWhenShown(true);
+        fTablePopupMenuManager.addMenuListener(manager -> {
+            TreeViewer viewer = getTreeViewer();
+            ISelection selection = viewer.getSelection();
+            if (selection instanceof IStructuredSelection) {
+                IStructuredSelection sel = (IStructuredSelection) selection;
+                if (manager != null) {
+                    appendToTablePopupMenu(manager, sel);
+                }
+            }
+        });
+        Menu tablePopup = fTablePopupMenuManager.createContextMenu(getTreeViewer().getTree());
+        Tree tree = getTreeViewer().getTree();
+        tree.setMenu(tablePopup);
+        tree.addDisposeListener(e -> {
+            if (fModule != null) {
+                fModule.dispose();
+            }
+        });
+    }
+
+    /** Provides label for the Segment Store tree viewer cells */
+    protected static class SegmentStoreStatisticsLabelProvider extends TreeLabelProvider {
+
+        @Override
+        public String getColumnText(@Nullable Object element, int columnIndex) {
+            String value = ""; //$NON-NLS-1$
+            if (element instanceof HiddenTreeViewerEntry) {
+                if (columnIndex == 0) {
+                    value = ((HiddenTreeViewerEntry) element).getName();
+                }
+            } else if (element instanceof SegmentStoreStatisticsEntry) {
+                SegmentStoreStatisticsEntry entry = (SegmentStoreStatisticsEntry) element;
+                if (columnIndex == 0) {
+                    return String.valueOf(entry.getName());
+                }
+                if (entry.getEntry().getNbElements() > 0) {
+                    if (columnIndex == 1) {
+                        value = toFormattedString(entry.getEntry().getMin());
+                    } else if (columnIndex == 2) {
+                        value = String.valueOf(toFormattedString(entry.getEntry().getMax()));
+                    } else if (columnIndex == 3) {
+                        value = String.valueOf(toFormattedString(entry.getEntry().getMean()));
+                    } else if (columnIndex == 4) {
+                        value = String.valueOf(toFormattedString(entry.getEntry().getStdDev()));
+                    } else if (columnIndex == 5) {
+                        value = String.valueOf(entry.getEntry().getNbElements());
+                    } else if (columnIndex == 6) {
+                        value = String.valueOf(toFormattedString(entry.getEntry().getTotal()));
+                    }
+                }
+            }
+            return checkNotNull(value);
+        }
+    }
+
+    /**
+     * Creates the statistics analysis module
+     *
+     * @return the statistics analysis module
+     */
+    @Nullable
+    protected abstract TmfAbstractAnalysisModule createStatisticsAnalysiModule();
+
+    /**
+     * Gets the statistics analysis module
+     *
+     * @return the statistics analysis module
+     */
+    @Nullable
+    public TmfAbstractAnalysisModule getStatisticsAnalysisModule() {
+        return fModule;
+    }
+
+    @Override
+    protected ITmfTreeColumnDataProvider getColumnDataProvider() {
+        return new ITmfTreeColumnDataProvider() {
+
+            @Override
+            public List<@Nullable TmfTreeColumnData> getColumnData() {
+                /* All columns are sortable */
+                List<@Nullable TmfTreeColumnData> columns = new ArrayList<>();
+                TmfTreeColumnData column = new TmfTreeColumnData(COLUMN_NAMES[0]);
+                column.setAlignment(SWT.RIGHT);
+                column.setComparator(new ViewerComparator() {
+                    @Override
+                    public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+                        if ((e1 == null) || (e2 == null)) {
+                            return 0;
+                        }
+
+                        SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+                        SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+                        return n1.getName().compareTo(n2.getName());
+
+                    }
+                });
+                columns.add(column);
+                column = new TmfTreeColumnData(COLUMN_NAMES[1]);
+                column.setAlignment(SWT.RIGHT);
+                column.setComparator(new ViewerComparator() {
+                    @Override
+                    public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+                        if ((e1 == null) || (e2 == null)) {
+                            return 0;
+                        }
+
+                        SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+                        SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+                        return Long.compare(n1.getEntry().getMin(), n2.getEntry().getMin());
+
+                    }
+                });
+                columns.add(column);
+                column = new TmfTreeColumnData(COLUMN_NAMES[2]);
+                column.setAlignment(SWT.RIGHT);
+                column.setComparator(new ViewerComparator() {
+                    @Override
+                    public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+                        if ((e1 == null) || (e2 == null)) {
+                            return 0;
+                        }
+
+                        SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+                        SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+                        return Long.compare(n1.getEntry().getMax(), n2.getEntry().getMax());
+
+                    }
+                });
+                columns.add(column);
+                column = new TmfTreeColumnData(COLUMN_NAMES[3]);
+                column.setAlignment(SWT.RIGHT);
+                column.setComparator(new ViewerComparator() {
+                    @Override
+                    public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+                        if ((e1 == null) || (e2 == null)) {
+                            return 0;
+                        }
+
+                        SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+                        SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+                        return Double.compare(n1.getEntry().getMean(), n2.getEntry().getMean());
+
+                    }
+                });
+                columns.add(column);
+                column = new TmfTreeColumnData(COLUMN_NAMES[4]);
+                column.setAlignment(SWT.RIGHT);
+                column.setComparator(new ViewerComparator() {
+                    @Override
+                    public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+                        if ((e1 == null) || (e2 == null)) {
+                            return 0;
+                        }
+
+                        SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+                        SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+                        return Double.compare(n1.getEntry().getStdDev(), n2.getEntry().getStdDev());
+
+                    }
+                });
+                columns.add(column);
+                column = new TmfTreeColumnData(COLUMN_NAMES[5]);
+                column.setAlignment(SWT.RIGHT);
+                column.setComparator(new ViewerComparator() {
+                    @Override
+                    public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+                        if ((e1 == null) || (e2 == null)) {
+                            return 0;
+                        }
+
+                        SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+                        SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+                        return Long.compare(n1.getEntry().getNbElements(), n2.getEntry().getNbElements());
+
+                    }
+                });
+                columns.add(column);
+                column = new TmfTreeColumnData(COLUMN_NAMES[6]);
+                column.setAlignment(SWT.RIGHT);
+                column.setComparator(new ViewerComparator() {
+                    @Override
+                    public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+                        if ((e1 == null) || (e2 == null)) {
+                            return 0;
+                        }
+
+                        SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+                        SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+                        return Double.compare(n1.getEntry().getTotal(), n2.getEntry().getTotal());
+
+                    }
+                });
+                columns.add(column);
+                column = new TmfTreeColumnData(""); //$NON-NLS-1$
+                columns.add(column);
+                return columns;
+            }
+
+        };
+    }
+
+    @Override
+    public void initializeDataSource() {
+        ITmfTrace trace = getTrace();
+        if (trace != null) {
+            TmfAbstractAnalysisModule module = createStatisticsAnalysiModule();
+            if (module == null) {
+                return;
+            }
+            try {
+                module.setTrace(trace);
+                module.schedule();
+                if (fModule != null) {
+                    fModule.dispose();
+                }
+                fModule = module;
+            } catch (TmfAnalysisException e) {
+                Activator.getDefault().logError("Error initializing statistics analysis module", e); //$NON-NLS-1$
+            }
+        }
+    }
+
+    /**
+     * Method to add commands to the context sensitive menu.
+     *
+     * @param manager
+     *            the menu manager
+     * @param sel
+     *            the current selection
+     */
+    protected void appendToTablePopupMenu(IMenuManager manager, IStructuredSelection sel) {
+        Object element = sel.getFirstElement();
+        if ((element instanceof SegmentStoreStatisticsEntry) && !(element instanceof HiddenTreeViewerEntry)) {
+            final SegmentStoreStatisticsEntry segment = (SegmentStoreStatisticsEntry) element;
+            IAction gotoStartTime = new Action(Messages.SegmentStoreStatisticsViewer_GotoMinAction) {
+                @Override
+                public void run() {
+                    ISegment minObject = segment.getEntry().getMinObject();
+                    long start = minObject == null ? 0 : minObject.getStart();
+                    long end = minObject == null ? 0 : minObject.getEnd();
+                    broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentsStatisticsViewer.this, TmfTimestamp.fromNanos(start), TmfTimestamp.fromNanos(end)));
+                    updateContent(start, end, true);
+                }
+            };
+
+            IAction gotoEndTime = new Action(Messages.SegmentStoreStatisticsViewer_GotoMaxAction) {
+                @Override
+                public void run() {
+                    ISegment maxObject = segment.getEntry().getMaxObject();
+                    long start = maxObject == null ? 0 : maxObject.getStart();
+                    long end = maxObject == null ? 0 : maxObject.getEnd();
+                    broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentsStatisticsViewer.this, TmfTimestamp.fromNanos(start), TmfTimestamp.fromNanos(end)));
+                    updateContent(start, end, true);
+                }
+            };
+
+            manager.add(gotoStartTime);
+            manager.add(gotoEndTime);
+        }
+    }
+
+    /**
+     * Formats a double value string
+     *
+     * @param value
+     *            a value to format
+     * @return formatted value
+     */
+    protected static String toFormattedString(double value) {
+        // The cast to long is needed because the formatter cannot truncate the
+        // number.
+        String percentageString = String.format("%s", FORMATTER.format(value)); //$NON-NLS-1$
+        return percentageString;
+    }
+
+    /**
+     * Class for defining an entry in the statistics tree.
+     */
+    protected class SegmentStoreStatisticsEntry extends TmfTreeViewerEntry {
+
+        private final IStatistics<ISegment> fEntry;
+
+        /**
+         * Constructor
+         *
+         * @param name
+         *            name of entry
+         *
+         * @param entry
+         *            segment store statistics object
+         */
+        public SegmentStoreStatisticsEntry(String name, IStatistics<ISegment> entry) {
+            super(name);
+            fEntry = entry;
+        }
+
+        /**
+         * Gets the statistics object
+         *
+         * @return statistics object
+         */
+        public IStatistics<ISegment> getEntry() {
+            return fEntry;
+        }
+
+    }
+
+    @Override
+    protected @Nullable ITmfTreeViewerEntry updateElements(long start, long end, boolean isSelection) {
+
+        TmfAbstractAnalysisModule analysisModule = getStatisticsAnalysisModule();
+
+        if (getTrace() == null || !(analysisModule instanceof AbstractSegmentStatisticsAnalysis)) {
+            return null;
+        }
+
+        AbstractSegmentStatisticsAnalysis module = (AbstractSegmentStatisticsAnalysis) analysisModule;
+
+        module.waitForCompletion();
+
+        TmfTreeViewerEntry root = new TmfTreeViewerEntry(""); //$NON-NLS-1$
+        List<ITmfTreeViewerEntry> entryList = root.getChildren();
+
+        if (isSelection) {
+            setStats(start, end, entryList, module, true, new NullProgressMonitor());
+        }
+        setStats(start, end, entryList, module, false, new NullProgressMonitor());
+        return root;
+    }
+
+    private void setStats(long start, long end, List<ITmfTreeViewerEntry> entryList, AbstractSegmentStatisticsAnalysis module, boolean isSelection, IProgressMonitor monitor) {
+        String label = isSelection ? getSelectionLabel() : getTotalLabel();
+        final IStatistics<ISegment> entry = isSelection ? module.getStatsForRange(start, end, monitor) : module.getStatsTotal();
+        if (entry != null) {
+
+            if (entry.getNbElements() == 0) {
+                return;
+            }
+            TmfTreeViewerEntry child = new SegmentStoreStatisticsEntry(checkNotNull(label), entry);
+            entryList.add(child);
+
+            final Map<@NonNull String, IStatistics<ISegment>> perTypeStats = isSelection ? module.getStatsPerTypeForRange(start, end, monitor) : module.getStatsPerType();
+            for (Entry<@NonNull String, IStatistics<ISegment>> statsEntry : perTypeStats.entrySet()) {
+                child.addChild(new SegmentStoreStatisticsEntry(statsEntry.getKey(), statsEntry.getValue()));
+            }
+        }
+    }
+
+    @Override
+    @TmfSignalHandler
+    public void windowRangeUpdated(@Nullable TmfWindowRangeUpdatedSignal signal) {
+        // Do nothing. We do not want to update the view and lose the selection
+        // if the window range is updated with current selection outside of this
+        // new range.
+    }
+
+    /**
+     * Get the type label
+     *
+     * @return the label
+     * @since 1.2
+     */
+    protected String getTypeLabel() {
+        return checkNotNull(Messages.AbstractSegmentStoreStatisticsViewer_types);
+    }
+
+    /**
+     * Get the total column label
+     *
+     * @return the totals column label
+     * @since 1.2
+     */
+    protected String getTotalLabel() {
+        return checkNotNull(Messages.AbstractSegmentStoreStatisticsViewer_total);
+    }
+
+    /**
+     * Get the selection column label
+     *
+     * @return The selection column label
+     * @since 1.2
+     */
+    protected String getSelectionLabel() {
+        return checkNotNull(Messages.AbstractSegmentStoreStatisticsViewer_selection);
+    }
+
+    /**
+     * Class to define a level in the tree that doesn't have any values.
+     */
+    protected class HiddenTreeViewerEntry extends SegmentStoreStatisticsEntry {
+        /**
+         * Constructor
+         *
+         * @param name
+         *            the name of the level
+         */
+        public HiddenTreeViewerEntry(String name) {
+            super(name, new Statistics<>(s -> s.getLength()));
+        }
+    }
+
+}
index 13ca84d1fc9fafcb97a9345c617e7d0d09ea3da6..9aafc1c77dd456bc20d86306a0fa05781fa589f0 100644 (file)
@@ -12,17 +12,17 @@ import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jface.util.IPropertyChangeListener;
 import org.eclipse.jface.util.PropertyChangeEvent;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsView;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentsStatisticsView;
 import org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.TmfXmlUiStrings;
 import org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.views.XmlLatencyViewInfo;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
 
 /**
  * The statistic view for pattern latency analysis
  *
  * @author Jean-Christian Kouame
  */
-public class PatternStatisticsView extends AbstractSegmentStoreStatisticsView {
+public class PatternStatisticsView extends AbstractSegmentsStatisticsView {
 
     private PatternStatisticsViewer fViewer;
     /** The view's ID */
@@ -56,7 +56,7 @@ public class PatternStatisticsView extends AbstractSegmentStoreStatisticsView {
     }
 
     @Override
-    protected @NonNull AbstractSegmentStoreStatisticsViewer createSegmentStoreStatisticsViewer(@NonNull Composite parent) {
+    protected @NonNull AbstractTmfTreeViewer createSegmentStoreStatisticsViewer(@NonNull Composite parent) {
         PatternStatisticsViewer viewer = new PatternStatisticsViewer(parent);
         fViewer = viewer;
         loadStatisticView();
index 916a788fdd01f4171ad77397da98a14f9d4fde3d..9838aac28d35ef22856999c0a6d4e8b3e3cdb2bb 100644 (file)
@@ -11,7 +11,7 @@ package org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.views.latency;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentsStatisticsViewer;
 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.XmlPatternLatencyStatisticsAnalysis;
 import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
 
@@ -20,7 +20,7 @@ import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
  *
  * @author Jean-Christian Kouame
  */
-public class PatternStatisticsViewer extends AbstractSegmentStoreStatisticsViewer {
+public class PatternStatisticsViewer extends AbstractSegmentsStatisticsViewer {
 
     private String fAnalysisId;
 
This page took 0.056099 seconds and 5 git commands to generate.