blob: 59d347f5c2cb3a389a0b65dde40db4bb8be85dd4 [file] [log] [blame]
/**********************************************************************
* Copyright (c) 2018 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicLong;
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.tracecompass.analysis.timing.core.segmentstore.SegmentStoreStatisticsModel;
import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.AbstractSegmentStatisticsAnalysis;
import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
import org.eclipse.tracecompass.internal.tmf.core.model.AbstractTmfTraceDataProvider;
import org.eclipse.tracecompass.internal.tmf.core.model.filters.FetchParametersUtils;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderParameterUtils;
import org.eclipse.tracecompass.tmf.core.model.CommonStatusMessage;
import org.eclipse.tracecompass.tmf.core.model.filters.FilterTimeQueryFilter;
import org.eclipse.tracecompass.tmf.core.model.filters.TimeQueryFilter;
import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataProvider;
import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeModel;
import org.eclipse.tracecompass.tmf.core.response.ITmfResponse.Status;
import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
/**
* This data provider will supply a statistics tree for an
* {@link AbstractSegmentStatisticsAnalysis}. Passing a
* {@link FilterTimeQueryFilter} will also return the statistics from the
* selected range.
*
* @author Loic Prieur-Drevon
* @since 4.0
*/
public class SegmentStoreStatisticsDataProvider extends AbstractTmfTraceDataProvider
implements ITmfTreeDataProvider<SegmentStoreStatisticsModel> {
/**
* Base {@link SegmentStoreStatisticsDataProvider} prefix
*/
public static final String ID = "org.eclipse.tracecompass.analysis.timing.core.segmentstore.SegmentStoreStatisticsDataProvider"; //$NON-NLS-1$
private static final String STATISTICS_SUFFIX = ".statistics"; //$NON-NLS-1$
private static final String TOTAL_PREFIX = "Total_"; //$NON-NLS-1$
private static final String SELECTION_PREFIX = "Selection_"; //$NON-NLS-1$
private static final Map<AbstractSegmentStatisticsAnalysis, SegmentStoreStatisticsDataProvider> PROVIDER_MAP = new WeakHashMap<>();
private static final AtomicLong ENTRY_ID = new AtomicLong();
private final AbstractSegmentStatisticsAnalysis fProvider;
private final String fId;
private final Map<String, Long> fIdToType = new HashMap<>();
private final long fTraceId = ENTRY_ID.getAndIncrement();
/**
* Get an instance of {@link SegmentStoreStatisticsDataProvider} for a trace and
* provider. Returns a null instance if the ISegmentStoreProvider is null. If
* the provider is an instance of {@link IAnalysisModule}, analysis is also
* scheduled.
*
* @param trace
* A trace on which we are interested to fetch a model
* @param module
* the ID of the analysis to generate this provider from.
* @return An instance of SegmentStoreDataProvider. Returns a null if the
* ISegmentStoreProvider is null.
*/
public static synchronized @Nullable SegmentStoreStatisticsDataProvider getOrCreate(ITmfTrace trace, AbstractSegmentStatisticsAnalysis module) {
// TODO experiment support.
return PROVIDER_MAP.computeIfAbsent(module, p -> new SegmentStoreStatisticsDataProvider(trace, p, module.getId() + STATISTICS_SUFFIX));
}
/**
* Constructor
*
* @param trace
* the trace for which this provider will supply info
* @param provider
* the segment statistics module from which to get data
* @param id
* the extension point ID
*/
public SegmentStoreStatisticsDataProvider(ITmfTrace trace, AbstractSegmentStatisticsAnalysis provider, String id) {
super(trace);
fId = id;
fProvider = provider;
}
@Deprecated
@Override
public TmfModelResponse<List<SegmentStoreStatisticsModel>> fetchTree(TimeQueryFilter filter, @Nullable IProgressMonitor monitor) {
Map<String, Object> parameters = FetchParametersUtils.timeQueryToMap(filter);
TmfModelResponse<@NonNull TmfTreeModel<@NonNull SegmentStoreStatisticsModel>> response = fetchTree(parameters, monitor);
TmfTreeModel<@NonNull SegmentStoreStatisticsModel> model = response.getModel();
List<SegmentStoreStatisticsModel> treeModel = null;
if (model != null) {
treeModel = model.getEntries();
}
return new TmfModelResponse<>(treeModel, response.getStatus(), response.getStatusMessage());
}
@Override
public TmfModelResponse<TmfTreeModel<SegmentStoreStatisticsModel>> fetchTree(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
if (monitor != null) {
fProvider.waitForCompletion(monitor);
if (monitor.isCanceled()) {
return new TmfModelResponse<>(null, Status.CANCELLED, CommonStatusMessage.TASK_CANCELLED);
}
} else {
fProvider.waitForCompletion();
}
IStatistics<ISegment> statsTotal = fProvider.getStatsTotal();
if (statsTotal == null) {
return new TmfModelResponse<>(null, Status.FAILED, CommonStatusMessage.ANALYSIS_INITIALIZATION_FAILED);
}
List<SegmentStoreStatisticsModel> list = new ArrayList<>();
list.add(new SegmentStoreStatisticsModel(fTraceId, -1, Collections.singletonList(Objects.requireNonNull(getTrace().getName())), statsTotal));
/*
* Add statistics for full duration.
*/
long totalId = getUniqueId(TOTAL_PREFIX);
list.add(new SegmentStoreStatisticsModel(totalId, fTraceId, Collections.singletonList(Objects.requireNonNull(Messages.SegmentStoreStatisticsDataProvider_Total)), statsTotal));
Map<String, IStatistics<ISegment>> totalStats = fProvider.getStatsPerType();
for (Entry<String, IStatistics<ISegment>> entry : totalStats.entrySet()) {
list.add(new SegmentStoreStatisticsModel(getUniqueId(TOTAL_PREFIX + entry.getKey()), totalId, Collections.singletonList(entry.getKey()), entry.getValue()));
}
/*
* Add statistics for selection if any.
*/
TimeQueryFilter filter = FetchParametersUtils.createTimeQuery(fetchParameters);
Boolean isFiltered = DataProviderParameterUtils.extractIsFiltered(fetchParameters);
if (filter != null && isFiltered != null && isFiltered) {
long start = filter.getStart();
long end = filter.getEnd();
IProgressMonitor nonNullMonitor = monitor != null ? monitor : new NullProgressMonitor();
IStatistics<ISegment> statsForRange = fProvider.getStatsForRange(start, end, nonNullMonitor);
if (statsForRange == null) {
return new TmfModelResponse<>(null, Status.CANCELLED, CommonStatusMessage.TASK_CANCELLED);
}
long selectionId = getUniqueId(SELECTION_PREFIX);
list.add(new SegmentStoreStatisticsModel(selectionId, fTraceId, Collections.singletonList(Objects.requireNonNull(Messages.SegmentStoreStatisticsDataProvider_Selection)), statsForRange));
Map<String, IStatistics<ISegment>> selectionStats = fProvider.getStatsPerTypeForRange(start, end, nonNullMonitor);
for (Entry<String, IStatistics<ISegment>> entry : selectionStats.entrySet()) {
list.add(new SegmentStoreStatisticsModel(getUniqueId(SELECTION_PREFIX + entry.getKey()), selectionId, Collections.singletonList(entry.getKey()), entry.getValue()));
}
}
return new TmfModelResponse<>(new TmfTreeModel<>(Collections.emptyList(), Collections.unmodifiableList(list)), Status.COMPLETED, CommonStatusMessage.COMPLETED);
}
private long getUniqueId(String name) {
return fIdToType.computeIfAbsent(name, n -> ENTRY_ID.getAndIncrement());
}
@Override
public String getId() {
return fId;
}
@Override
public void dispose() {
fIdToType.clear();
fProvider.dispose();
}
}