blob: f54d309a1b5af2afc5d0c5ee4136a0e15e8b58d7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2022 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
*
* Contributors:
* Kyrollos Bekhet - Initial API and implementation
******************************************************************************/
package org.eclipse.tracecompass.analysis.timing.core.segmentstore;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.common.core.log.TraceCompassLog;
import org.eclipse.tracecompass.common.core.log.TraceCompassLogUtils.ScopeLog;
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.exceptions.TmfAnalysisException;
import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
/**
* @author Kyrollos Bekhet
* @since 5.3
*/
public class SegmentStoreAnalysisModule extends AbstractSegmentStoreAnalysisModule {
private static class SegmentAspectWrapper implements ISegmentAspect {
private ISegmentAspect fAspect;
public SegmentAspectWrapper(ISegmentAspect aspect) {
fAspect = aspect;
}
@Override
public String getName() {
return fAspect.getName();
}
@Override
public String getHelpText() {
return fAspect.getHelpText();
}
@Override
public @Nullable Comparator<?> getComparator() {
return fAspect.getComparator();
}
@Override
public @Nullable Object resolve(ISegment segment) {
if (segment instanceof TraceNameSegment) {
return fAspect.resolve(((TraceNameSegment) segment).getSegment());
}
return fAspect.resolve(segment);
}
}
private static class SegmentAspectTraceName implements ISegmentAspect {
public static final ISegmentAspect INSTANCE = new SegmentAspectTraceName();
@Override
public @Nullable Object resolve(ISegment segment) {
if (segment instanceof TraceNameSegment) {
return ((TraceNameSegment) segment).getTraceName();
}
return null;
}
@Override
public String getName() {
return "Trace"; //$NON-NLS-1$
}
@Override
public String getHelpText() {
return ""; //$NON-NLS-1$
}
@Override
public @Nullable Comparator<?> getComparator() {
return Comparator.comparing(TraceNameSegment::getTraceName);
}
}
private static class TraceNameSegment implements ISegment {
private static final long serialVersionUID = 5122084433695846745L;
private String fTraceName;
private ISegment fSegment;
/**
* @param traceName
* The trace name
* @param segment
* The segment to encapsulate inside this class
*/
public TraceNameSegment(String traceName, ISegment segment) {
fSegment = segment;
fTraceName = traceName;
}
public String getTraceName() {
return fTraceName;
}
@Override
public long getStart() {
return fSegment.getStart();
}
@Override
public long getEnd() {
return fSegment.getEnd();
}
/**
* @return the segment encapsulated in this wrapper class
*/
public ISegment getSegment() {
return fSegment;
}
}
private static final Logger LOGGER = TraceCompassLog.getLogger(SegmentStoreAnalysisModule.class);
private static final Map<ISegmentAspect, ISegmentAspect> fAspects = new HashMap<>();
private Map<String, ISegmentStoreProvider> fProviders;
private @Nullable String fName;
/**
* Constructor only used for test purposes
*
* @param trace
* The trace to analyse
* @throws TmfAnalysisException
* Exception thrown if analysis fails
*/
@VisibleForTesting
public SegmentStoreAnalysisModule(ITmfTrace trace) throws TmfAnalysisException {
fProviders = new HashMap<>();
setTrace(trace);
if (trace instanceof TmfExperiment) {
for (ITmfTrace tr : TmfTraceManager.getTraceSet(trace)) {
IAnalysisModule m = tr.getAnalysisModules().iterator().next();
addAnalysis(m, String.valueOf(tr.getName()));
}
} else {
IAnalysisModule m = trace.getAnalysisModules().iterator().next();
addAnalysis(m, String.valueOf(trace.getName()));
}
}
/**
* @param trace
* The trace to analyse
* @param id
* The ID of the analysis
*/
public SegmentStoreAnalysisModule(ITmfTrace trace, String id) {
fProviders = new HashMap<>();
if (trace instanceof TmfExperiment) {
for (ITmfTrace tr : TmfTraceManager.getTraceSet(trace)) {
IAnalysisModule m = tr.getAnalysisModule(id);
if (m != null) {
addAnalysis(m, String.valueOf(tr.getName()));
}
}
} else {
IAnalysisModule m = trace.getAnalysisModule(id);
if (m != null) {
addAnalysis(m, String.valueOf(trace.getName()));
}
}
}
private void addAnalysis(IAnalysisModule module, String traceName) {
if (module instanceof ISegmentStoreProvider) {
fName = module.getName();
module.schedule();
fProviders.putIfAbsent(traceName, (ISegmentStoreProvider) module);
}
}
@Override
public String getName() {
return NonNullUtils.nullToEmptyString(fName);
}
@Override
protected boolean buildAnalysisSegments(ISegmentStore<ISegment> segmentStore, IProgressMonitor monitor) throws TmfAnalysisException {
try (ScopeLog scope = new ScopeLog(LOGGER, Level.FINER, "SegmentStoreAnalysisModule#buildAnalysisSegment")) { //$NON-NLS-1$
if (fProviders.size() == 0) {
return false;
}
if (fProviders.size() == 1) {
segmentStore.addAll(Objects.requireNonNull(fProviders.get(fProviders.keySet().iterator().next())).getSegmentStore());
} else {
for (Entry<String, ISegmentStoreProvider> providerEntry : fProviders.entrySet()) {
ISegmentStore<ISegment> segments = Objects.requireNonNull(providerEntry.getValue()).getSegmentStore();
if (segments != null) {
for (ISegment segment : segments) {
segmentStore.add(new TraceNameSegment(providerEntry.getKey(), segment));
}
}
}
}
}
return true;
}
@Override
public void dispose() {
for (Entry<String, ISegmentStoreProvider> providerEntry : fProviders.entrySet()) {
ISegmentStoreProvider provider = Objects.requireNonNull(providerEntry.getValue());
if (provider instanceof IAnalysisModule) {
((IAnalysisModule) provider).dispose();
}
}
super.dispose();
}
@Override
protected void canceling() {
// Do nothing
}
@Override
public Iterable<ISegmentAspect> getSegmentAspects() {
if (fProviders.size() > 1) {
return getExperimentSegmentAspects();
}
ITmfTrace trace = getTrace();
if (trace != null) {
ISegmentStoreProvider provider = fProviders.get(trace.getName());
if (provider != null) {
return provider.getSegmentAspects();
}
}
return Collections.emptyList();
}
@Override
protected boolean executeAnalysis(IProgressMonitor monitor) throws TmfAnalysisException {
for (Entry<String, ISegmentStoreProvider> providerEntry : fProviders.entrySet()) {
ISegmentStoreProvider provider = Objects.requireNonNull(providerEntry.getValue());
if (provider instanceof IAnalysisModule) {
((IAnalysisModule) provider).waitForCompletion(monitor);
}
}
return super.executeAnalysis(monitor);
}
private Iterable<ISegmentAspect> getExperimentSegmentAspects() {
ImmutableSet.Builder<ISegmentAspect> builder = new ImmutableSet.Builder<>();
ISegmentStoreProvider provider = fProviders.get(fProviders.keySet().iterator().next());
if (provider != null) {
builder.addAll(getWrapperAspects(provider.getSegmentAspects()));
}
builder.add(SegmentAspectTraceName.INSTANCE);
return builder.build();
}
private static List<ISegmentAspect> getWrapperAspects(Iterable<ISegmentAspect> aspects) {
List<ISegmentAspect> wrappedAspects = new ArrayList<>();
for (ISegmentAspect aspect : aspects) {
synchronized (fAspects) {
ISegmentAspect wrapperAspect = fAspects.computeIfAbsent(aspect, a -> new SegmentAspectWrapper(aspect));
wrappedAspects.add(wrapperAspect);
}
}
return wrappedAspects;
}
}