*******************************************************************************/
package org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics;
-import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
-
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+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;
import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import com.google.common.collect.ImmutableList;
* Abstract analysis to build statistics data for a segment store
*
* @author Jean-Christian Kouame
+ * @since 3.0
*/
public abstract class AbstractSegmentStatisticsAnalysis extends TmfAbstractAnalysisModule {
- private @Nullable IAnalysisModule fSegmentStoreProviderModule;
+ private static Function<ISegment, Long> FCT_LENGTH = s -> s.getLength();
+
+ private @Nullable ISegmentStoreProvider fSegmentStoreProviderModule;
- private @Nullable SegmentStoreStatistics fTotalStats;
+ private @Nullable IStatistics<ISegment> fTotalStats;
- private @Nullable Map<String, SegmentStoreStatistics> fPerSegmentTypeStats;
+ private Map<String, IStatistics<ISegment>> fPerSegmentTypeStats = new HashMap<>();
@Override
protected Iterable<IAnalysisModule> getDependentAnalyses() {
ITmfTrace trace = getTrace();
if (trace != null) {
ISegmentStoreProvider provider = getSegmentProviderAnalysis(trace);
+ fSegmentStoreProviderModule = provider;
if (provider instanceof IAnalysisModule) {
- fSegmentStoreProviderModule = (IAnalysisModule) provider;
return ImmutableList.of((IAnalysisModule) provider);
}
}
@Override
protected boolean executeAnalysis(IProgressMonitor monitor) throws TmfAnalysisException {
- IAnalysisModule segmentStoreProviderModule = fSegmentStoreProviderModule;
- ITmfTrace trace = getTrace();
- if (!(segmentStoreProviderModule instanceof ISegmentStoreProvider) || (trace == null)) {
+ if (monitor.isCanceled()) {
return false;
}
- segmentStoreProviderModule.waitForCompletion();
- ISegmentStore<ISegment> segStore = ((ISegmentStoreProvider) segmentStoreProviderModule).getSegmentStore();
+ IStatistics<ISegment> totalStats = getTotalStats(TmfTimeRange.ETERNITY.getStartTime().toNanos(), TmfTimeRange.ETERNITY.getEndTime().toNanos(), monitor);
+ if (totalStats == null) {
+ return false;
+ }
- if (segStore != null) {
+ Map<String, IStatistics<ISegment>> perTypeStats = getPerTypeStats(TmfTimeRange.ETERNITY.getStartTime().toNanos(), TmfTimeRange.ETERNITY.getEndTime().toNanos(), monitor);
+ fTotalStats = totalStats;
+ fPerSegmentTypeStats = perTypeStats;
- boolean result = calculateTotalManual(segStore, monitor);
+ return true;
+ }
- if (!result) {
- return false;
- }
+ private @Nullable IStatistics<ISegment> getTotalStats(long start, long end, IProgressMonitor monitor) {
+ Iterable<@NonNull ISegment> store = getSegmentStore(start, end);
+ if (store == null) {
+ return null;
+ }
+ if (monitor.isCanceled()) {
+ return null;
+ }
+ return calculateTotalManual(store, monitor);
+ }
- result = calculateTotalPerType(segStore, monitor);
- if (!result) {
- return false;
- }
+ /**
+ * 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 getStatsTotal();
}
- return true;
+ return getTotalStats(start, end, monitor);
}
- private boolean calculateTotalManual(ISegmentStore<ISegment> store, IProgressMonitor monitor) {
- SegmentStoreStatistics total = new SegmentStoreStatistics();
- Iterator<ISegment> iter = store.iterator();
+ 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() || store == null) {
+ return Collections.EMPTY_MAP;
+ }
+ return calculateTotalPerType(store, monitor);
+ }
+
+ /**
+ * 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 getStatsPerType();
+ }
+ return getPerTypeStats(start, end, monitor);
+ }
+
+ /**
+ * Get the segment store from which we want the statistics
+ *
+ * @return The segment store
+ */
+ private @Nullable Iterable<@NonNull ISegment> getSegmentStore(long start, long end) {
+ ISegmentStoreProvider segmentStoreProviderModule = fSegmentStoreProviderModule;
+ if (segmentStoreProviderModule == null) {
+ return null;
+ }
+ if (segmentStoreProviderModule instanceof IAnalysisModule) {
+ ((IAnalysisModule) segmentStoreProviderModule).waitForCompletion();
+ }
+ long t0 = start;
+ long t1 = end;
+ if (end < start) {
+ t0 = end;
+ t1 = start;
+ }
+ ISegmentStore<@NonNull ISegment> segmentStore = segmentStoreProviderModule.getSegmentStore();
+ return segmentStore != null ? t0 != TmfTimeRange.ETERNITY.getStartTime().toNanos() || t1 != TmfTimeRange.ETERNITY.getEndTime().toNanos() ?
+ (Iterable<@NonNull ISegment>) segmentStore.getIntersectingElements(t0, t1) : segmentStore
+ : Collections.emptyList();
+ }
+
+ 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()) {
- return false;
+ return null;
}
ISegment segment = iter.next();
- total.update(checkNotNull(segment));
+ total.update(segment);
}
- fTotalStats = total;
- return true;
+ return total;
}
- private boolean calculateTotalPerType(ISegmentStore<ISegment> store, 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 = store.iterator();
+ Iterator<ISegment> iter = segments.iterator();
while (iter.hasNext()) {
if (monitor.isCanceled()) {
- return false;
+ return Collections.EMPTY_MAP;
}
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);
}
}
- fPerSegmentTypeStats = perSegmentTypeStats;
- return true;
+ return perSegmentTypeStats;
}
/**
}
/**
- * The total statistics
+ * Get the statistics for the full segment store
*
- * @return the total statistics
+ * @return The complete statistics
+ * @since 1.3
*/
- public @Nullable SegmentStoreStatistics getTotalStats() {
+ public @Nullable IStatistics<ISegment> getStatsTotal() {
return fTotalStats;
}
/**
- * The per syscall statistics
+ * Get the statistics for each type of segment in this segment store
*
- * @return the per syscall statistics
+ * @return the map of statistics per type
+ * @since 1.3
*/
- public @Nullable Map<String, SegmentStoreStatistics> getPerSegmentTypeStats() {
+ public Map<String, IStatistics<ISegment>> getStatsPerType() {
return fPerSegmentTypeStats;
}