From 1e718a5cd62d949f5ca1ec3957da0d1f8a397f72 Mon Sep 17 00:00:00 2001 From: Bernd Hufmann Date: Thu, 4 Apr 2024 18:54:53 -0400 Subject: [PATCH] WIP: Retrieve Thread context from ThreadStatusDataProvider Context: threadName, threadId, hostId This also sends the TmfThreadSelectedSignal to configure the critical path execution. Notes: API is not final. The data provider should be configured differently Signed-off-by: Bernd Hufmann --- .../OSCriticalPathDataProviderFactory.java | 31 ++++++++++++++ .../ThreadStatusDataProvider.java | 41 +++++++++++++++++++ .../core/model/tree/ITmfTreeDataProvider.java | 19 +++++++++ .../tree/TmfTreeCompositeDataProvider.java | 23 +++++++++++ 4 files changed, 114 insertions(+) diff --git a/analysis/org.eclipse.tracecompass.analysis.graph.core/src/org/eclipse/tracecompass/internal/analysis/graph/core/dataprovider/OSCriticalPathDataProviderFactory.java b/analysis/org.eclipse.tracecompass.analysis.graph.core/src/org/eclipse/tracecompass/internal/analysis/graph/core/dataprovider/OSCriticalPathDataProviderFactory.java index b97b829b54..78e1a47d80 100644 --- a/analysis/org.eclipse.tracecompass.analysis.graph.core/src/org/eclipse/tracecompass/internal/analysis/graph/core/dataprovider/OSCriticalPathDataProviderFactory.java +++ b/analysis/org.eclipse.tracecompass.analysis.graph.core/src/org/eclipse/tracecompass/internal/analysis/graph/core/dataprovider/OSCriticalPathDataProviderFactory.java @@ -11,15 +11,21 @@ package org.eclipse.tracecompass.internal.analysis.graph.core.dataprovider; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tracecompass.analysis.graph.core.criticalpath.AbstractCriticalPathModule; import org.eclipse.tracecompass.analysis.graph.core.criticalpath.OSCriticalPathModule; import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; +import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor; +import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor.ProviderType; import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderFactory; +import org.eclipse.tracecompass.tmf.core.model.DataProviderDescriptor; import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataModel; import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataProvider; import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; @@ -27,6 +33,8 @@ import org.eclipse.tracecompass.tmf.core.signal.TmfStartAnalysisSignal; import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal; 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; /** * {@link IDataProviderFactory} for the {@link CriticalPathDataProvider} @@ -37,6 +45,14 @@ public class OSCriticalPathDataProviderFactory implements IDataProviderFactory { private final Map map = new HashMap<>(); + + private static final IDataProviderDescriptor DESCRIPTOR = new DataProviderDescriptor.Builder() + .setId(CriticalPathDataProvider.ID) + .setName(Objects.requireNonNull("Critical Path")) + .setDescription(Objects.requireNonNull("Critical Path")) + .setProviderType(ProviderType.TIME_GRAPH) + .build(); + /** * Constructor, registers the module with the {@link TmfSignalManager} */ @@ -46,6 +62,16 @@ public OSCriticalPathDataProviderFactory() { @Override public @Nullable ITmfTreeDataProvider createProvider(@NonNull ITmfTrace trace) { + ITmfTrace localTrace = trace; + if (localTrace instanceof TmfExperiment) { + for(ITmfTrace tr: TmfTraceManager.getTraceSet(trace)) { + ITmfTreeDataProvider pr = createProvider(tr); + if (pr != null) { + return pr; + } + } + } + OSCriticalPathModule module = map.remove(trace); if (module == null) { // the DataProviderManager does not negative cache @@ -54,6 +80,11 @@ public OSCriticalPathDataProviderFactory() { return new OSCriticalPathDataProvider(trace, module); } + @Override + public Collection getDescriptors(@NonNull ITmfTrace trace) { + return Collections.singletonList(DESCRIPTOR); + } + /** * {@link TmfSignalHandler} for when {@link AbstractCriticalPathModule} is started, as * the analysis is not registered with the trace, we use this to know to diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/threadstatus/ThreadStatusDataProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/threadstatus/ThreadStatusDataProvider.java index 82f294d4fd..c70c54a115 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/threadstatus/ThreadStatusDataProvider.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/threadstatus/ThreadStatusDataProvider.java @@ -32,8 +32,10 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tracecompass.analysis.os.linux.core.event.aspect.LinuxTidAspect; +import org.eclipse.tracecompass.analysis.os.linux.core.model.HostThread; import org.eclipse.tracecompass.analysis.os.linux.core.model.OsStrings; import org.eclipse.tracecompass.analysis.os.linux.core.model.ProcessStatus; +import org.eclipse.tracecompass.analysis.os.linux.core.signals.TmfThreadSelectedSignal; import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace; import org.eclipse.tracecompass.internal.analysis.os.linux.core.Activator; import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes; @@ -78,6 +80,7 @@ import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeModel; import org.eclipse.tracecompass.tmf.core.response.ITmfResponse; import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse; +import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; @@ -177,6 +180,7 @@ public class ThreadStatusDataProvider extends AbstractTmfTraceDataProvider imple /** Cache for entry metadata */ private final Map> fEntryMetadata = new HashMap<>(); + private final Map fEntryModel = new HashMap<>(); private IOutputAnnotationProvider fEventAnnotationProvider; @@ -274,6 +278,7 @@ public ThreadStatusDataProvider(@NonNull ITmfTrace trace, TmfStateSystemAnalysis for (TimeGraphEntryModel model : list) { fEntryMetadata.put(model.getId(), model.getMetadata()); + fEntryModel.put(model.getId(), model); } if (complete) { @@ -825,4 +830,40 @@ public TmfModelResponse fetchStyle(Map fetchPa public @NonNull TmfModelResponse<@NonNull AnnotationModel> fetchAnnotations(@NonNull Map<@NonNull String, @NonNull Object> fetchParameters, @Nullable IProgressMonitor monitor) { return fEventAnnotationProvider.fetchAnnotations(fetchParameters, monitor); } + + @Override + public @NonNull TmfModelResponse<@NonNull Map<@NonNull String, @NonNull Object>> fetchTreeContext(@NonNull Map<@NonNull String, @NonNull Object> fetchParameters, @Nullable IProgressMonitor monitor) { + // TODO Auto-generated method stub + fModule.waitForInitialization(); + ITmfStateSystem ss = fModule.getStateSystem(); + if (ss == null) { + return new TmfModelResponse<>(null, ITmfResponse.Status.FAILED, CommonStatusMessage.ANALYSIS_INITIALIZATION_FAILED); + } + + /* + * As we are caching the intermediate result, we only want a single thread to + * update them. + */ + synchronized (fBuildMap) { + List selectedItems = DataProviderParameterUtils.extractSelectedItems(fetchParameters); + if (selectedItems != null && selectedItems.size() > 0) { + Long id = selectedItems.get(0); + TimeGraphEntryModel model = fEntryModel.get(id); + if (model instanceof ThreadEntryModel) { + Map retMap = new HashMap<>(); + ThreadEntryModel mod = (ThreadEntryModel) model; + retMap.put("name", mod.getName()); + retMap.put("tid", mod.getThreadId()); + retMap.put("hostId", getTrace().getHostId()); + + // Not restful ... + HostThread hostThread = new HostThread(getTrace().getHostId(), mod.getThreadId()); + TmfThreadSelectedSignal signal = new TmfThreadSelectedSignal(this, hostThread); + TmfSignalManager.dispatchSignal(signal); + return new TmfModelResponse<>(retMap, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED); + } + } + } + return ITimeGraphDataProvider.super.fetchTreeContext(fetchParameters, monitor); + } } diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/ITmfTreeDataProvider.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/ITmfTreeDataProvider.java index f7056af531..37fb659109 100644 --- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/ITmfTreeDataProvider.java +++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/ITmfTreeDataProvider.java @@ -15,6 +15,8 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.model.CommonStatusMessage; +import org.eclipse.tracecompass.tmf.core.response.ITmfResponse; import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse; /** @@ -43,6 +45,23 @@ public interface ITmfTreeDataProvider { */ TmfModelResponse> fetchTree(Map fetchParameters, @Nullable IProgressMonitor monitor); + /** + * This methods computes a tree model context. Then, it returns a + * {@link TmfModelResponse} that contains the model. Tree model will be used + * by tree viewer to show entries as a tree or flat hierarchy + * + * @param fetchParameters + * A query filter that contains an array of time. Times are used + * for requesting data. + * @param monitor + * A ProgressMonitor to cancel task + * @return A {@link TmfModelResponse} instance + * @since 9.3 + */ + default TmfModelResponse> fetchTreeContext(Map fetchParameters, @Nullable IProgressMonitor monitor) { + return new TmfModelResponse<>(null, ITmfResponse.Status.CANCELLED, CommonStatusMessage.COMPLETED); + } + /** * This method return the extension point ID of this provider * diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/TmfTreeCompositeDataProvider.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/TmfTreeCompositeDataProvider.java index 68eff1b601..2eab67d533 100644 --- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/TmfTreeCompositeDataProvider.java +++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/TmfTreeCompositeDataProvider.java @@ -250,5 +250,28 @@ public TmfModelResponse fetchAnnotations(Map fe } return new TmfModelResponse<>(model, ITmfResponse.Status.RUNNING, CommonStatusMessage.RUNNING); } + + @Override + public TmfModelResponse> fetchTreeContext(Map fetchParameters, @Nullable IProgressMonitor monitor) { + boolean isComplete = true; + Map model = new HashMap<>(); + for (P dataProvider : getProviders()) { + TmfModelResponse> response = dataProvider.fetchTreeContext(fetchParameters, monitor); + isComplete &= response.getStatus() == ITmfResponse.Status.COMPLETED; + if (monitor != null && monitor.isCanceled()) { + return new TmfModelResponse<>(null, ITmfResponse.Status.CANCELLED, CommonStatusMessage.TASK_CANCELLED); + } + Map retModel = response.getModel(); + if (retModel != null && !retModel.isEmpty()) { + model = retModel; + // only one data provider should return the context + break; + } + } + if (isComplete) { + return new TmfModelResponse<>(model, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED); + } + return new TmfModelResponse<>(model, ITmfResponse.Status.RUNNING, CommonStatusMessage.RUNNING); + } }