tmf.core: move Custom marker logic to core
Allow markers to be treated as regular annotations.
The internal notion of a max duration was removed as it should
be filtered at the request level.
This can:
* Filter on categories
* Handle multiple annotations sources
[Added] Dataprovider support for custom annotations
[Added] Server-side annotations filtering
[Deprecated] org.eclipse.tracecompass.tmf.ui.markers.IMarkerReferenceProvider
Change-Id: I0278193b1f954c5bc54e490e9feda7016a190c89
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/c/tracecompass/org.eclipse.tracecompass/+/179329
Tested-by: Patrick Tasse <patrick.tasse@gmail.com>
Tested-by: Trace Compass Bot <tracecompass-bot@eclipse.org>
Reviewed-by: Patrick Tasse <patrick.tasse@gmail.com>
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/META-INF/MANIFEST.MF b/tmf/org.eclipse.tracecompass.tmf.core/META-INF/MANIFEST.MF
index b99c5aa..f799b9b 100644
--- a/tmf/org.eclipse.tracecompass.tmf.core/META-INF/MANIFEST.MF
+++ b/tmf/org.eclipse.tracecompass.tmf.core/META-INF/MANIFEST.MF
@@ -16,7 +16,8 @@
org.eclipse.cdt.core,
org.eclipse.tracecompass.datastore.core,
org.eclipse.tracecompass.tmf.filter.parser,
- org.eclipse.jdt.annotation;bundle-version="[2.0.0,3.0.0)";resolution:=optional
+ org.eclipse.jdt.annotation;bundle-version="[2.0.0,3.0.0)";resolution:=optional,
+ org.apache.commons.lang3
Export-Package: org.eclipse.tracecompass.internal.provisional.tmf.core.model,
org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations;x-internal:=true,
org.eclipse.tracecompass.internal.provisional.tmf.core.model.events;x-friends:="org.eclipse.tracecompass.tmf.core.tests",
@@ -27,6 +28,7 @@
org.eclipse.tracecompass.internal.tmf.core;x-friends:="org.eclipse.tracecompass.tmf.core.tests,org.eclipse.tracecompass.tmf.ui.swtbot.tests",
org.eclipse.tracecompass.internal.tmf.core.analysis;x-friends:="org.eclipse.tracecompass.tmf.core.tests",
org.eclipse.tracecompass.internal.tmf.core.analysis.callsite;x-friends:="org.eclipse.tracecompass.analysis.os.linux.core.tests",
+ org.eclipse.tracecompass.internal.tmf.core.annotations;x-internal:=true,
org.eclipse.tracecompass.internal.tmf.core.aspect;x-internal:=true,
org.eclipse.tracecompass.internal.tmf.core.callstack;x-friends:="org.eclipse.tracecompass.tmf.ui,org.eclipse.tracecompass.tmf.core.tests",
org.eclipse.tracecompass.internal.tmf.core.component;x-friends:="org.eclipse.tracecompass.tmf.core.tests",
@@ -42,6 +44,7 @@
org.eclipse.tracecompass.analysis.counters.core,
org.eclipse.tracecompass.analysis.profiling.core,
org.eclipse.tracecompass.tmf.core.tests",
+ org.eclipse.tracecompass.internal.tmf.core.model.annontations;x-internal:=true,
org.eclipse.tracecompass.internal.tmf.core.model.filters;
x-friends:="org.eclipse.tracecompass.analysis.counters.ui,
org.eclipse.tracecompass.analysis.graph.core,
@@ -111,6 +114,7 @@
org.eclipse.tracecompass.tmf.core.filter.model,
org.eclipse.tracecompass.tmf.core.filter.xml,
org.eclipse.tracecompass.tmf.core.io,
+ org.eclipse.tracecompass.tmf.core.markers,
org.eclipse.tracecompass.tmf.core.model,
org.eclipse.tracecompass.tmf.core.model.filters,
org.eclipse.tracecompass.tmf.core.model.timegraph,
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/provisional/tmf/core/model/annotations/CustomAnnotationProvider.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/provisional/tmf/core/model/annotations/CustomAnnotationProvider.java
new file mode 100644
index 0000000..2e575cf
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/provisional/tmf/core/model/annotations/CustomAnnotationProvider.java
@@ -0,0 +1,360 @@
+/*******************************************************************************
+ * Copyright (c) 2021 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.provisional.tmf.core.model.annotations;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.internal.tmf.core.markers.IMarkerConstants;
+import org.eclipse.tracecompass.internal.tmf.core.markers.Marker;
+import org.eclipse.tracecompass.internal.tmf.core.markers.Marker.PeriodicMarker;
+import org.eclipse.tracecompass.internal.tmf.core.markers.MarkerSegment;
+import org.eclipse.tracecompass.internal.tmf.core.markers.MarkerSet;
+import org.eclipse.tracecompass.internal.tmf.core.markers.SubMarker;
+import org.eclipse.tracecompass.internal.tmf.core.markers.SubMarker.SplitMarker;
+import org.eclipse.tracecompass.internal.tmf.core.markers.SubMarker.WeightedMarker;
+import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderParameterUtils;
+import org.eclipse.tracecompass.tmf.core.dataprovider.X11ColorUtils;
+import org.eclipse.tracecompass.tmf.core.markers.ITimeReference;
+import org.eclipse.tracecompass.tmf.core.markers.ITimeReferenceProvider;
+import org.eclipse.tracecompass.tmf.core.markers.TimeReference;
+import org.eclipse.tracecompass.tmf.core.model.OutputElementStyle;
+import org.eclipse.tracecompass.tmf.core.model.StyleProperties;
+import org.eclipse.tracecompass.tmf.core.presentation.RGBAColor;
+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;
+
+/**
+ * Custom Annotation Provider
+ *
+ * @author Matthew Khouzam
+ */
+public class CustomAnnotationProvider implements IOutputAnnotationProvider {
+
+ private static final String DEFAULT_COLOR = "blue"; //$NON-NLS-1$
+ private static final long MIN_PERIOD = 5; // in units of resolution
+ // intervals
+ private static final int ALPHA = 10;
+ private static final String COLOR_REGEX = "#[A-Fa-f0-9]{6}"; //$NON-NLS-1$
+
+ private List<IOutputAnnotationProvider> fMarkerEventSources = new ArrayList<>();
+ private Map<Marker, RGBAColor> fColors = new HashMap<>();
+ private final @Nullable ITmfTrace fTrace;
+ private @Nullable MarkerSet fMarkerSet;
+
+ /**
+ * Custom Annotation Provider for a given marker set
+ *
+ * @param trace
+ * the trace to make the annotations on. Used to get the start
+ * time, if null, the epoch is assumed to be the reference time.
+ * @param markerSet
+ * the marker set, a definition of a group of configurable
+ * markers
+ */
+ public CustomAnnotationProvider(@Nullable ITmfTrace trace, @Nullable MarkerSet markerSet) {
+ fTrace = trace;
+ fMarkerSet = markerSet;
+ fMarkerEventSources = configure(markerSet);
+ }
+
+ /**
+ * Configure the marker source from the specified marker set
+ *
+ * @param markerSet
+ * the marker set, or null to clear the configuration
+ * @return the list of {@link IOutputAnnotationProvider}s for this marker
+ * set
+ */
+ public List<IOutputAnnotationProvider> configure(@Nullable MarkerSet markerSet) {
+ List<IOutputAnnotationProvider> markerEventSources = new ArrayList<>();
+ if (markerSet != null) {
+ for (Marker marker : markerSet.getMarkers()) {
+ markerEventSources.add(configure(Objects.requireNonNull(marker)));
+ }
+ }
+ fMarkerEventSources = markerEventSources;
+ fMarkerSet = markerSet;
+ return markerEventSources;
+ }
+
+ private IOutputAnnotationProvider configure(Marker marker) {
+ if (marker instanceof PeriodicMarker) {
+ PeriodicMarker periodicMarker = (PeriodicMarker) marker;
+ long rollover = periodicMarker.getRange().hasUpperBound() ? (periodicMarker.getRange().upperEndpoint() - periodicMarker.getRange().lowerEndpoint() + 1) : 0;
+ RGBAColor evenColor = getColor(marker);
+ RGBAColor oddColor = getOddColor(evenColor);
+ ITmfTrace trace = fTrace;
+ double period = IMarkerConstants.convertToNanos(periodicMarker.getPeriod(), periodicMarker.getUnit(), trace);
+ String referenceId = periodicMarker.getReferenceId();
+ ITimeReference baseReference = null;
+ if (trace instanceof IAdaptable && !referenceId.isEmpty()) {
+ ITimeReferenceProvider adapter = ((IAdaptable) trace).getAdapter(ITimeReferenceProvider.class);
+ if (adapter != null) {
+ baseReference = adapter.apply(referenceId);
+ }
+ }
+ if (baseReference == null) {
+ baseReference = ITimeReference.ZERO;
+ }
+ ITimeReference reference = new TimeReference(baseReference.getTime() + Math.round(IMarkerConstants.convertToNanos(periodicMarker.getOffset(), periodicMarker.getUnit(), trace)), baseReference.getIndex());
+ return new PeriodicAnnotationSource(marker, reference.getIndex(), reference.getTime(), period, rollover, evenColor, oddColor);
+ }
+ throw new IllegalArgumentException("Marker must be of type PeriodicMarker or SubMarker"); //$NON-NLS-1$
+
+ }
+
+ private void getSubMarkerList(SubMarker subMarker, Annotation markerEvent, Map<String, Collection<@NonNull Annotation>> markerMap, long startTime, long endTime, long minDuration, Long[] times) {
+ if (subMarker instanceof SplitMarker) {
+ getSubMarkerList((SplitMarker) subMarker, markerEvent, markerMap, startTime, endTime, minDuration, times);
+ } else if (subMarker instanceof WeightedMarker) {
+ getSubMarkerList((WeightedMarker) subMarker, markerEvent, markerMap, startTime, endTime, minDuration, times);
+ }
+ }
+
+ private void getSubMarkerList(SplitMarker splitMarker, Annotation markerEvent, Map<String, Collection<@NonNull Annotation>> annotationMap, long startTime, long endTime, long minDuration, Long[] times) {
+ if (markerEvent.getTime() > endTime || markerEvent.getTime() + markerEvent.getDuration() < startTime) {
+ return;
+ }
+ long lower = splitMarker.getRange().lowerEndpoint();
+ long upper = splitMarker.getRange().upperEndpoint();
+ long segments = upper - lower + 1;
+ long start = markerEvent.getTime();
+ List<@NonNull Annotation> annotationList = new ArrayList<>();
+ for (int i = 0; i < segments; i++) {
+ long end = markerEvent.getTime() + Math.round((double) (i + 1) / segments * markerEvent.getDuration());
+ long duration = end - start;
+ long labelIndex = lower + i;
+ if (end >= startTime && duration > minDuration && splitMarker.getIndexRange().contains(labelIndex)) {
+ RGBAColor color = (labelIndex & 1) == 0 ? getColor(splitMarker) : getOddColor(getColor(splitMarker));
+ OutputElementStyle outputStyle = getOutputStyle(splitMarker, color);
+ Annotation subAnnotation = new Annotation(start, end - start, -1, String.format(splitMarker.getLabel(), labelIndex), outputStyle);
+ for (SubMarker subMarker : splitMarker.getSubMarkers()) {
+ getSubMarkerList(Objects.requireNonNull(subMarker), subAnnotation, annotationMap, startTime, endTime, minDuration, times);
+ }
+ annotationList.add(subAnnotation);
+ }
+ if (start >= endTime) {
+ break;
+ }
+ start = end;
+ }
+ populateMap(annotationMap, annotationList, Objects.requireNonNull(splitMarker.getName()));
+ }
+
+ private void getSubMarkerList(WeightedMarker weightedMarker, Annotation markerEvent, Map<String, Collection<@NonNull Annotation>> annotationMap, long startTime, long endTime, long minDuration, Long[] times) {
+ if (markerEvent.getTime() > endTime || markerEvent.getTime() + markerEvent.getDuration() < startTime) {
+ return;
+ }
+ long start = markerEvent.getTime();
+ long length = 0;
+ List<@NonNull Annotation> annotationsList = new ArrayList<>();
+ for (int i = 0; i < weightedMarker.getSegments().size(); i++) {
+ MarkerSegment segment = weightedMarker.getSegments().get(i);
+ length += segment.getLength();
+ long end = markerEvent.getTime() + Math.round((length / (double) weightedMarker.getTotalLength()) * markerEvent.getDuration());
+ long duration = end - start;
+ if (end >= startTime && duration > minDuration && !segment.getColor().isEmpty()) {
+ RGBAColor color = getColor(segment);
+ Annotation subAnnotation = new Annotation(start, end - start, -1, String.format(segment.getLabel(), i), getOutputStyle(segment, color));
+ for (SubMarker subMarker : segment.getSubMarkers()) {
+ getSubMarkerList(Objects.requireNonNull(subMarker), subAnnotation, annotationMap, startTime, endTime, minDuration, times);
+ }
+ for (SubMarker subMarker : weightedMarker.getSubMarkers()) {
+ getSubMarkerList(Objects.requireNonNull(subMarker), subAnnotation, annotationMap, startTime, endTime, minDuration, times);
+ }
+ annotationsList.add(subAnnotation);
+ }
+ if (start >= endTime) {
+ break;
+ }
+ start = end;
+ }
+ populateMap(annotationMap, annotationsList, Objects.requireNonNull(weightedMarker.getName()));
+ }
+
+ private static void populateMap(Map<String, Collection<@NonNull Annotation>> annotationMap, List<@NonNull Annotation> annotationsList, String name) {
+ Collection<@NonNull Annotation> annotations = annotationMap.get(name);
+ if (annotations != null) {
+ Set<@NonNull Annotation> annotationSet = new HashSet<>();
+ annotationSet.addAll(annotationsList);
+ annotationSet.addAll(annotations);
+ annotationMap.put(name, annotationSet);
+ } else {
+ annotationMap.put(name, annotationsList);
+ }
+ }
+
+ private RGBAColor getColor(Marker marker) {
+ RGBAColor color = fColors.get(marker);
+ if (color == null) {
+ color = parseColor(marker.getColor());
+ fColors.put(marker, color);
+ }
+ return color;
+ }
+
+ private static RGBAColor getOddColor(RGBAColor color) {
+ return new RGBAColor(color.getRed(), color.getGreen(), color.getBlue(), 0);
+ }
+
+ private static RGBAColor fromHexColor(@Nullable String color) {
+ if (color != null && color.matches(COLOR_REGEX)) {
+ return new RGBAColor(Integer.valueOf(color.substring(1, 3), 16),
+ Integer.valueOf(color.substring(3, 5), 16),
+ Integer.valueOf(color.substring(5, 7), 16), ALPHA);
+ }
+ return new RGBAColor(0, 0, 0, ALPHA);
+ }
+
+ private static RGBAColor parseColor(@Nullable String colorString) {
+ if (colorString == null) {
+ return fromHexColor(DEFAULT_COLOR);
+ }
+ if (colorString.matches(COLOR_REGEX)) {
+ return fromHexColor(colorString);
+ }
+ return fromHexColor(X11ColorUtils.toHexColor(colorString));
+ }
+
+ private Map<@NonNull String, @NonNull Collection<@NonNull Annotation>> getMarkers(Map<@NonNull String, @NonNull Object> fetchParams, @Nullable IProgressMonitor monitor) {
+ List<@NonNull Long> timeRequested = DataProviderParameterUtils.extractTimeRequested(fetchParams);
+ if (timeRequested == null || timeRequested.size() < 2) {
+ return Collections.emptyMap();
+ }
+ Set<@NonNull String> categoriesRequested = getCategories(fetchParams);
+ Long[] times = timeRequested.toArray(new Long[0]);
+ long starttime = timeRequested.get(0);
+ long endtime = timeRequested.get(timeRequested.size() - 1);
+ int resolution = (int) Math.min(Integer.MAX_VALUE, timeRequested.get(1) - timeRequested.get(0));
+ Map<@NonNull String, @NonNull Collection<@NonNull Annotation>> markerMap = new LinkedHashMap<>();
+ for (IOutputAnnotationProvider source : fMarkerEventSources) {
+ long minDuration = resolution * MIN_PERIOD;
+ if (source instanceof PeriodicAnnotationSource) {
+ PeriodicAnnotationSource periodicAnnotationSource = (PeriodicAnnotationSource) source;
+ long maxDuration = (long) periodicAnnotationSource.getPeriod();
+ if (maxDuration > minDuration) {
+ AnnotationModel model = periodicAnnotationSource.fetchAnnotations(fetchParams, monitor).getModel();
+ if (model != null) {
+ Map<@NonNull String, @NonNull Collection<@NonNull Annotation>> annotations = model.getAnnotations();
+ List<Annotation> markerList = new ArrayList<>();
+ for (Entry<@NonNull String, @NonNull Collection<@NonNull Annotation>> entryAnnotation : annotations.entrySet()) {
+ String category = Objects.requireNonNull(entryAnnotation.getKey());
+ if (!categoriesRequested.isEmpty() && !categoriesRequested.contains(category)) {
+ continue;
+ }
+ for (Annotation annotation : Objects.requireNonNull(entryAnnotation.getValue())) {
+ markerList.add(annotation);
+ for (SubMarker subMarker : periodicAnnotationSource.getMarker().getSubMarkers()) {
+ getSubMarkerList(Objects.requireNonNull(subMarker), annotation, markerMap, starttime, endtime, minDuration, times);
+
+ }
+ }
+ markerMap.put(category, markerList);
+ }
+ }
+ }
+ }
+ }
+ return markerMap;
+ }
+
+ private static Set<String> getCategories(Map<String, Object> fetchParams) {
+ Set<String> categories = new HashSet<>();
+ Object fetched = fetchParams.getOrDefault(DataProviderParameterUtils.REQUESTED_MARKER_CATEGORIES_KEY, Collections.emptyList());
+ if (fetched instanceof Iterable<?>) {
+ for (Object key : (Iterable<?>) fetched) {
+ if (key != null) {
+ categories.add(String.valueOf(key));
+ }
+ }
+ }
+ return categories;
+ }
+
+ private static OutputElementStyle getOutputStyle(Marker marker, RGBAColor color) {
+ Map<@NonNull String, @NonNull Object> style = new HashMap<>();
+ String name = marker.getName();
+ if (name != null) {
+ style.put(StyleProperties.STYLE_NAME, name);
+ }
+ style.put(StyleProperties.COLOR, color.toString().substring(0, 7));
+ style.put(StyleProperties.OPACITY, (float) (color.getAlpha() / 255.0));
+ return new OutputElementStyle(null, style);
+ }
+
+ @Override
+ public @NonNull TmfModelResponse<@NonNull AnnotationCategoriesModel> fetchAnnotationCategories(@NonNull Map<@NonNull String, @NonNull Object> fetchParameters, @Nullable IProgressMonitor monitor) {
+ List<@NonNull String> categories = new ArrayList<>();
+ for (IOutputAnnotationProvider source : fMarkerEventSources) {
+ TmfModelResponse<@NonNull AnnotationCategoriesModel> response = source.fetchAnnotationCategories(fetchParameters, monitor);
+ AnnotationCategoriesModel model = response.getModel();
+ if (model != null) {
+ categories.addAll(model.getAnnotationCategories());
+ }
+ }
+ return new TmfModelResponse<>(new AnnotationCategoriesModel(categories), Status.COMPLETED, ""); //$NON-NLS-1$
+ }
+
+ @Override
+ public @NonNull TmfModelResponse<@NonNull AnnotationModel> fetchAnnotations(@NonNull Map<@NonNull String, @NonNull Object> fetchParameters, @Nullable IProgressMonitor monitor) {
+ Map<@NonNull String, @NonNull Collection<@NonNull Annotation>> markers = getMarkers(fetchParameters, monitor);
+ return new TmfModelResponse<>(new AnnotationModel(markers), Status.COMPLETED, ""); //$NON-NLS-1$
+ }
+
+ /**
+ * Get Max Duration
+ *
+ * @return the maximum duration of all event sources
+ */
+ public double getMaxDuration() {
+ double duration = 0;
+ for (IOutputAnnotationProvider es : fMarkerEventSources) {
+ if (es instanceof PeriodicAnnotationSource) {
+ duration = Math.max(duration, ((PeriodicAnnotationSource) es).getPeriod());
+ }
+ }
+ return duration;
+ }
+
+ /**
+ * Get the label of the marker, may be a format string
+ *
+ * @return the label of the marker
+ */
+ public Map<String, String> getLabel() {
+ Map<String, String> labels = new HashMap<>();
+ if (fMarkerSet != null) {
+ for (Marker marker : fMarkerSet.getMarkers()) {
+ if (marker instanceof PeriodicMarker) {
+ PeriodicMarker periodicMarker = (PeriodicMarker) marker;
+ labels.put(Objects.requireNonNull(periodicMarker.getName()), Objects.requireNonNull(periodicMarker.getLabel()));
+ }
+ }
+ }
+ return labels;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/provisional/tmf/core/model/annotations/PeriodicAnnotationSource.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/provisional/tmf/core/model/annotations/PeriodicAnnotationSource.java
new file mode 100644
index 0000000..db1e828
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/provisional/tmf/core/model/annotations/PeriodicAnnotationSource.java
@@ -0,0 +1,289 @@
+/*******************************************************************************
+ * Copyright (c) 2021 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.provisional.tmf.core.model.annotations;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang3.math.Fraction;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.internal.tmf.core.markers.Marker;
+import org.eclipse.tracecompass.internal.tmf.core.markers.Marker.PeriodicMarker;
+import org.eclipse.tracecompass.internal.tmf.core.markers.SubMarker;
+import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderParameterUtils;
+import org.eclipse.tracecompass.tmf.core.markers.ITimeReference;
+import org.eclipse.tracecompass.tmf.core.markers.TimeReference;
+import org.eclipse.tracecompass.tmf.core.model.OutputElementStyle;
+import org.eclipse.tracecompass.tmf.core.model.StyleProperties;
+import org.eclipse.tracecompass.tmf.core.presentation.RGBAColor;
+import org.eclipse.tracecompass.tmf.core.response.ITmfResponse.Status;
+import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.RangeSet;
+
+/**
+ * Data provider for Periodic Markers (frames)
+ *
+ * @author Matthew Khouzam
+ * @since 6.3
+ */
+public class PeriodicAnnotationSource implements IOutputAnnotationProvider {
+ private static final TmfModelResponse<AnnotationModel> EMPTY_MODEL_RESPONSE = new TmfModelResponse<>(new AnnotationModel(Collections.emptyMap()), Status.COMPLETED, ""); //$NON-NLS-1$
+ private final String fCategory;
+ private final double fPeriod;
+ private final long fPeriodInteger;
+ private @Nullable Fraction fPeriodFraction;
+ private final long fRollover;
+ private final RGBAColor fColor1;
+ private final @Nullable RGBAColor fColor2;
+ private ITimeReference fReference;
+ /**
+ * TODO: remove later
+ */
+ private final Marker fMarker;
+
+ /**
+ * Creates a data provider for periodic markers. They alternate in color and
+ * can have sub markers.
+ *
+ * @param category
+ * the category marker, to reference submarkers and such
+ * @param index
+ * the index (number) of the reference frame
+ * @param time
+ * the time of the reference frame frame - the time of the frame refered by index.
+ * @param period
+ * the period of the markers, in ns
+ * @param rollover
+ * the rollover for the index. If it is 100, the indexes will
+ * increment 98->99->0-> ...
+ * @param color1
+ * the even color
+ * @param color2
+ * the odd color
+ */
+ public PeriodicAnnotationSource(Marker category, long index, long time, double period, long rollover, RGBAColor color1, @Nullable RGBAColor color2) {
+ fCategory = String.valueOf(category.getName());
+ fMarker = category;
+ fReference = new TimeReference(time, index);
+ fColor1 = color1;
+ fColor2 = color2;
+ fPeriod = period;
+ fPeriodInteger = (long) period;
+ try {
+ fPeriodFraction = Fraction.getFraction(fPeriod - fPeriodInteger);
+ } catch (ArithmeticException e) {
+ /* can't convert to fraction, use floating-point arithmetic */
+ fPeriodFraction = null;
+ }
+ fRollover = rollover;
+ }
+
+ /**
+ * Creates a data provider for periodic markers. They alternate in color and
+ * can have sub markers.
+ *
+ * @param category
+ * the category Name
+ * @param index
+ * the index (number) of the starting frame
+ * @param time
+ * the time of the starting frame
+ * @param period
+ * the period of the markers, in ns
+ * @param rollover
+ * the rollover for the index. If it is 100, the indexes will
+ * increment 98->99->0-> ...
+ * @param color1
+ * the even color
+ * @param color2
+ * the odd color
+ */
+ public PeriodicAnnotationSource(String category, long index, long time, double period, long rollover, RGBAColor color1, @Nullable RGBAColor color2) {
+ this(new Marker(category, "black") {}, index, time, period, rollover, color1, color2); //$NON-NLS-1$
+ }
+
+ /*
+ * Adjust to a reference that is closer to the start time, to avoid rounding
+ * errors in floating point calculations with large numbers.
+ */
+ private ITimeReference adjustReference(ITimeReference baseReference, long time) {
+ long offsetIndex = (long) ((time - baseReference.getTime()) / fPeriod);
+ long offsetTime = 0;
+ Fraction fraction = fPeriodFraction;
+ if (fraction != null) {
+ /*
+ * If period = int num/den, find an offset index that is an exact
+ * multiple of den and calculate index * period = (index * int) +
+ * (index / den * num), all exact calculations.
+ */
+ offsetIndex = offsetIndex - offsetIndex % fraction.getDenominator();
+ offsetTime = offsetIndex * fPeriodInteger + offsetIndex / fraction.getDenominator() * fraction.getNumerator();
+ } else {
+ /*
+ * Couldn't compute fractional part as fraction, use simple
+ * multiplication but with possible rounding error.
+ */
+ offsetTime = Math.round(offsetIndex * fPeriod);
+ }
+ return new TimeReference(baseReference.getTime() + offsetTime, baseReference.getIndex() + offsetIndex);
+ }
+
+ @Override
+ public @NonNull TmfModelResponse<@NonNull AnnotationCategoriesModel> fetchAnnotationCategories(@NonNull Map<@NonNull String, @NonNull Object> fetchParameters, @Nullable IProgressMonitor monitor) {
+ List<@NonNull String> categories = new ArrayList<>();
+ categories.add(fCategory);
+ getCategories(categories, getMarker());
+ /*
+ * We can have different sub-markers of the same category, we need them
+ * to be distinct
+ */
+ categories = categories.stream().distinct().collect(Collectors.toList());
+ return new TmfModelResponse<>(
+ new AnnotationCategoriesModel(categories), Status.COMPLETED, ""); //$NON-NLS-1$
+ }
+
+ private void getCategories(List<@NonNull String> categories, Marker marker) {
+ for (SubMarker sm : marker.getSubMarkers()) {
+ categories.add(String.valueOf(sm.getName()));
+ getCategories(categories, sm);
+ }
+ }
+
+ @Override
+ public @NonNull TmfModelResponse<@NonNull AnnotationModel> fetchAnnotations(@NonNull Map<@NonNull String, @NonNull Object> fetchParameters, @Nullable IProgressMonitor monitor) {
+ List<Long> times = DataProviderParameterUtils.extractTimeRequested(fetchParameters);
+ if (times == null) {
+ return EMPTY_MODEL_RESPONSE;
+ }
+ int size = times.size() - 1;
+ long startTime = times.get(0);
+ long endTime = times.get(size);
+ long resolution = (endTime - startTime) / (size);
+ if (startTime > endTime) {
+ return EMPTY_MODEL_RESPONSE;
+ }
+ long step = Math.max(Math.round(fPeriod), resolution);
+ OutputElementStyle[] styles = new OutputElementStyle[2];
+ styles[0] = generateOutputElementStyle(fColor1);
+ RGBAColor color2 = fColor2;
+ styles[1] = color2 == null ? styles[0] : generateOutputElementStyle(color2);
+
+ Collection<Annotation> annotations = new ArrayList<>();
+ /* Subtract 1.5 periods to ensure previous marker is included */
+ long time = startTime - Math.max(Math.round(1.5 * fPeriod), resolution);
+ ITimeReference reference = adjustReference(fReference, time);
+ Annotation annotation = null;
+ while (true) {
+ long index = Math.round((time - reference.getTime()) / fPeriod) + reference.getIndex();
+ long markerTime = Math.round((index - reference.getIndex()) * fPeriod) + reference.getTime();
+ long duration = (fColor2 == null) ? 0 : Math.round((index + 1 - reference.getIndex()) * fPeriod) + reference.getTime() - markerTime;
+
+ long labelIndex = index;
+ if (fRollover != 0) {
+ labelIndex %= fRollover;
+ if (labelIndex < 0) {
+ labelIndex += fRollover;
+ }
+ }
+ /* Add previous marker if current is visible */
+ if ((markerTime >= startTime || markerTime + duration > startTime) && annotation != null) {
+ annotations.add(annotation);
+ }
+ if (isApplicable(labelIndex)) {
+ OutputElementStyle style = Objects.requireNonNull((index % 2) == 0 ? styles[0] : styles[1]);
+ annotation = new Annotation(markerTime, duration, -1, String.valueOf(labelIndex), style);
+ } else {
+ annotation = null;
+ }
+ if (markerTime > endTime || (monitor != null && monitor.isCanceled())) {
+ if (annotation != null && isApplicable(labelIndex)) {
+ /* The next marker out of range is included */
+ annotations.add(annotation);
+ }
+ break;
+ }
+
+ time += step;
+ }
+ Map<String, Collection<Annotation>> model = new HashMap<>();
+ model.put(fCategory, annotations);
+ return new TmfModelResponse<>(new AnnotationModel(model), Status.COMPLETED, ""); //$NON-NLS-1$
+ }
+
+ private static OutputElementStyle generateOutputElementStyle(RGBAColor color) {
+ String colorString = color.toString().substring(0, 7);
+ return new OutputElementStyle(null,
+ ImmutableMap.of(StyleProperties.STYLE_NAME, colorString,
+ StyleProperties.COLOR, colorString,
+ StyleProperties.OPACITY, (float) (color.getAlpha() / 255.0)));
+ }
+
+ /**
+ * Period
+ *
+ * @return period in ns
+ */
+ public double getPeriod() {
+ return fPeriod;
+ }
+
+ /**
+ * Get the marker model
+ *
+ * @return the marker that this annotation provider is modeled on
+ */
+ public Marker getMarker() {
+ return fMarker;
+ }
+
+ /**
+ * Get the base index (starting index) for a marker
+ *
+ * @return the base index
+ */
+ public long getBaseIndex() {
+ Marker marker = getMarker();
+ if (marker instanceof PeriodicMarker) {
+ return ((PeriodicMarker) marker).getOffset();
+ }
+ return 0;
+ }
+
+ /**
+ * Is this index applicable?
+ *
+ * @param index
+ * the index to look at
+ * @return true if it applies
+ */
+ public boolean isApplicable(long index) {
+ Marker marker = getMarker();
+ if (marker instanceof PeriodicMarker) {
+ PeriodicMarker periodicMarker = (PeriodicMarker) marker;
+ RangeSet<@Nullable Long> indexRange = periodicMarker.getIndexRange();
+ if (indexRange != null) {
+ return indexRange.contains(periodicMarker.getOffset() + index);
+ }
+ }
+ return true;
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/Activator.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/Activator.java
index 586d399..f64012e 100644
--- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/Activator.java
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/Activator.java
@@ -19,10 +19,13 @@
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.internal.tmf.core.annotations.CustomDefinedOutputAnnotationProviderFactory;
import org.eclipse.tracecompass.tmf.core.analysis.TmfAnalysisManager;
import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderManager;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
import org.eclipse.tracecompass.tmf.core.symbols.SymbolProviderManager;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceAdapterManager;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
import org.osgi.framework.BundleContext;
@@ -48,6 +51,7 @@
* The shared instance
*/
private static Activator fPlugin;
+ private static final CustomDefinedOutputAnnotationProviderFactory CUSTOM_DEFINED_OUTPUT_ANNOTATION_PROVIDER_FACTORY = new CustomDefinedOutputAnnotationProviderFactory();
// ------------------------------------------------------------------------
// Constructors
@@ -95,10 +99,13 @@
SymbolProviderManager.getInstance();
/* Initialize the data provider manager */
DataProviderManager.getInstance();
+ TmfTraceAdapterManager.registerFactory(CUSTOM_DEFINED_OUTPUT_ANNOTATION_PROVIDER_FACTORY, ITmfTrace.class);
}
@Override
public void stop(BundleContext context) throws Exception {
+ TmfTraceAdapterManager.unregisterFactory(CUSTOM_DEFINED_OUTPUT_ANNOTATION_PROVIDER_FACTORY);
+ CUSTOM_DEFINED_OUTPUT_ANNOTATION_PROVIDER_FACTORY.dispose();
TmfCoreTracer.stop();
TmfTraceManager.getInstance().dispose();
TmfAnalysisManager.dispose();
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/CustomDefinedOutputAnnotationProvider.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/CustomDefinedOutputAnnotationProvider.java
new file mode 100644
index 0000000..07bf048
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/CustomDefinedOutputAnnotationProvider.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2021 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.tmf.core.annotations;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.AnnotationCategoriesModel;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.AnnotationModel;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.CustomAnnotationProvider;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.IOutputAnnotationProvider;
+import org.eclipse.tracecompass.internal.tmf.core.markers.MarkerConfigXmlParser;
+import org.eclipse.tracecompass.internal.tmf.core.markers.MarkerSet;
+import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderParameterUtils;
+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;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+
+/**
+ * Trace Annotation provider for providing custom (frame) annotations. This one
+ * is a singleton for all of trace compass, it encapsulates the individual
+ * annotation providers per trace.
+ */
+public class CustomDefinedOutputAnnotationProvider implements IOutputAnnotationProvider {
+
+ private static final String INVALID_MARKER_ID = "Invalid marker ID %s"; //$NON-NLS-1$
+ private static final String NO_MARKER_ID = "no markerID"; //$NON-NLS-1$
+ private final Map<String, Map<String, CustomAnnotationProvider>> fTraceMarkers = Collections.synchronizedMap(new HashMap<>());
+
+ /**
+ * Constructor
+ */
+ public CustomDefinedOutputAnnotationProvider() {
+ MarkerConfigXmlParser.initMarkerSets();
+ }
+
+ @Override
+ public TmfModelResponse<AnnotationCategoriesModel> fetchAnnotationCategories(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
+ Object markerID = fetchParameters.get(DataProviderParameterUtils.REQUESTED_MARKER_SET_KEY);
+ Object hostID = fetchParameters.get(DataProviderParameterUtils.REQUESTED_TRACE_KEY);
+ Optional<ITmfTrace> activeTrace = getTrace(hostID);
+ if (markerID == null) {
+ return new TmfModelResponse<>(null, Status.FAILED, NO_MARKER_ID);
+ }
+ MarkerSet ms = getMarkerSet(markerID);
+ if (ms != null) {
+ return getAnnotationProvider(String.valueOf(hostID), activeTrace.get(), ms).fetchAnnotationCategories(fetchParameters, monitor);
+ }
+ return new TmfModelResponse<>(null, Status.FAILED, formatError(markerID));
+ }
+
+ @Override
+ public TmfModelResponse<AnnotationModel> fetchAnnotations(Map<String, Object> fetchParameters, @Nullable IProgressMonitor monitor) {
+ Object markerID = fetchParameters.get(DataProviderParameterUtils.REQUESTED_MARKER_SET_KEY);
+ Object hostID = fetchParameters.get(DataProviderParameterUtils.REQUESTED_TRACE_KEY);
+ Optional<ITmfTrace> activeTrace = getTrace(hostID);
+ if (markerID == null) {
+ return new TmfModelResponse<>(null, Status.FAILED, NO_MARKER_ID);
+ }
+ MarkerSet ms = getMarkerSet(markerID);
+ if (ms != null) {
+ return getAnnotationProvider(String.valueOf(hostID), activeTrace.isPresent() ? activeTrace.get() : null, ms).fetchAnnotations(fetchParameters, monitor);
+ }
+ return new TmfModelResponse<>(null, Status.FAILED, formatError(markerID));
+ }
+
+ private CustomAnnotationProvider getAnnotationProvider(String hostID, @Nullable ITmfTrace activeTrace, MarkerSet ms) {
+ Map<String, CustomAnnotationProvider> capMap = fTraceMarkers.computeIfAbsent(hostID, e -> Collections.synchronizedMap(new HashMap<>()));
+ return capMap.computeIfAbsent(ms.getId(), a -> new CustomAnnotationProvider(activeTrace, ms));
+ }
+
+ private static @Nullable MarkerSet getMarkerSet(Object markerID) {
+ Optional<@Nullable MarkerSet> markerOptional = MarkerConfigXmlParser.getMarkerSets().stream()
+ .filter(markerSet -> Objects.equals(markerID, markerSet.getId()))
+ .findAny();
+ if (markerOptional.isPresent()) {
+ return markerOptional.get();
+ }
+ return null;
+ }
+
+ private static Optional<ITmfTrace> getTrace(Object hostID) {
+ return TmfTraceManager.getInstance().getOpenedTraces().stream().flatMap(trace -> TmfTraceManager.getTraceSetWithExperiment(trace).stream()).filter(t -> Objects.equals(t.getHostId(), hostID)).findAny();
+ }
+
+ private static String formatError(Object markerID) {
+ return String.format(INVALID_MARKER_ID, markerID);
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/markers/LostEventsOutputAnnotationProviderFactory.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/CustomDefinedOutputAnnotationProviderFactory.java
similarity index 63%
copy from tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/markers/LostEventsOutputAnnotationProviderFactory.java
copy to tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/CustomDefinedOutputAnnotationProviderFactory.java
index 86161ea..0f81ee4 100644
--- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/markers/LostEventsOutputAnnotationProviderFactory.java
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/CustomDefinedOutputAnnotationProviderFactory.java
@@ -9,23 +9,22 @@
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
-package org.eclipse.tracecompass.internal.tmf.core.markers;
+package org.eclipse.tracecompass.internal.tmf.core.annotations;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.IOutputAnnotationProvider;
-import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.LostEventOutputAnnotationProvider;
import org.eclipse.tracecompass.tmf.core.trace.AbstractTmfTraceAdapterFactory;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
/**
- * Output annotation provider factory for trace level annotations for lost events.
+ * Output annotation provider factory for trace level annotations for custom annotations (frames).
*/
-public class LostEventsOutputAnnotationProviderFactory extends AbstractTmfTraceAdapterFactory {
+public class CustomDefinedOutputAnnotationProviderFactory extends AbstractTmfTraceAdapterFactory {
@Override
- protected <T> T getTraceAdapter(ITmfTrace trace, Class<T> adapterType) {
- if (IOutputAnnotationProvider.class.equals(adapterType)) {
- IOutputAnnotationProvider adapter = new LostEventOutputAnnotationProvider(trace);
- return adapterType.cast(adapter);
+ protected @Nullable <T> T getTraceAdapter(ITmfTrace trace, @Nullable Class<T> adapterType) {
+ if (null != adapterType && IOutputAnnotationProvider.class.equals(adapterType)) {
+ return adapterType.cast(new CustomDefinedOutputAnnotationProvider());
}
return null;
}
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/markers/LostEventsOutputAnnotationProviderFactory.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/LostEventsOutputAnnotationProviderFactory.java
similarity index 82%
rename from tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/markers/LostEventsOutputAnnotationProviderFactory.java
rename to tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/LostEventsOutputAnnotationProviderFactory.java
index 86161ea..9e1c0d8 100644
--- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/markers/LostEventsOutputAnnotationProviderFactory.java
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/LostEventsOutputAnnotationProviderFactory.java
@@ -9,8 +9,9 @@
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
-package org.eclipse.tracecompass.internal.tmf.core.markers;
+package org.eclipse.tracecompass.internal.tmf.core.annotations;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.IOutputAnnotationProvider;
import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.LostEventOutputAnnotationProvider;
import org.eclipse.tracecompass.tmf.core.trace.AbstractTmfTraceAdapterFactory;
@@ -22,8 +23,8 @@
public class LostEventsOutputAnnotationProviderFactory extends AbstractTmfTraceAdapterFactory {
@Override
- protected <T> T getTraceAdapter(ITmfTrace trace, Class<T> adapterType) {
- if (IOutputAnnotationProvider.class.equals(adapterType)) {
+ protected <T> @Nullable T getTraceAdapter(ITmfTrace trace, @Nullable Class<T> adapterType) {
+ if (null != adapterType && IOutputAnnotationProvider.class.equals(adapterType)) {
IOutputAnnotationProvider adapter = new LostEventOutputAnnotationProvider(trace);
return adapterType.cast(adapter);
}
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/package-info.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/package-info.java
new file mode 100644
index 0000000..71eee61
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/annotations/package-info.java
@@ -0,0 +1,13 @@
+/**********************************************************************
+ * Copyright (c) 2021 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
+ **********************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.tmf.core.annotations;
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/markers/IMarkerConstants.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/markers/IMarkerConstants.java
index 9800354..dc38d3d 100644
--- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/markers/IMarkerConstants.java
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/markers/IMarkerConstants.java
@@ -14,6 +14,11 @@
package org.eclipse.tracecompass.internal.tmf.core.markers;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.tmf.core.trace.ICyclesConverter;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+
/**
* Marker constants
*
@@ -65,4 +70,42 @@
String NS = "ns"; //$NON-NLS-1$
/** Cycles unit */
String CYCLES = "cycles"; //$NON-NLS-1$
+
+ /** Nanoseconds to milliseconds */
+ long NANO_PER_MILLI = 1000000L;
+ /** Nanoseconds to microseconds */
+ long NANO_PER_MICRO = 1000L;
+
+ /**
+ * Converter for a number with unit to
+ *
+ * @param number
+ * the value of the time to be converted, for 314 us it would be
+ * 314.
+ * @param unit
+ * the unit, {@link IMarkerConstants#MS},
+ * {@link IMarkerConstants#US},{@link IMarkerConstants#NS} or
+ * {@link IMarkerConstants#CYCLES}
+ * @param trace
+ * needed for cycle conversion, can be {@code null}
+ * @return a double of nanoseconds. Note, will lose precision for UTC times,
+ * but it is needed to not accumulate errors. This makes sense in
+ * the context of "periodic markers"
+ */
+ static double convertToNanos(double number, String unit, @Nullable ITmfTrace trace) {
+ if (unit.equalsIgnoreCase(MS)) {
+ return number * NANO_PER_MILLI;
+ } else if (unit.equalsIgnoreCase(US)) {
+ return number * NANO_PER_MICRO;
+ } else if (unit.equalsIgnoreCase(NS)) {
+ return number;
+ } else if (unit.equalsIgnoreCase(CYCLES) &&
+ trace instanceof IAdaptable) {
+ ICyclesConverter adapter = ((IAdaptable) trace).getAdapter(ICyclesConverter.class);
+ if (adapter != null) {
+ return adapter.cyclesToNanos((long) number);
+ }
+ }
+ return number;
+ }
}
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/DataProviderParameterUtils.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/DataProviderParameterUtils.java
index 5eae25b..5389e99 100644
--- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/DataProviderParameterUtils.java
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/DataProviderParameterUtils.java
@@ -67,6 +67,26 @@
public static final String REQUESTED_ELEMENT_KEY = "requested_element"; //$NON-NLS-1$
/**
+ * Requested marker set key
+ * @since 7.0
+ */
+ public static final String REQUESTED_MARKER_SET_KEY = "requested_marker_set"; //$NON-NLS-1$
+
+ /**
+ * Requested marker categories key
+ * @since 7.0
+ */
+ public static final String REQUESTED_MARKER_CATEGORIES_KEY = "requested_marker_categories"; //$NON-NLS-1$
+
+ /**
+ * Requested trace key, uses the hostID, as the time is the same for every
+ * trace with the same host id.
+ *
+ * @since 7.0
+ */
+ public static final String REQUESTED_TRACE_KEY = "requested_trace"; //$NON-NLS-1$
+
+ /**
* Key to extract isFiltered from parameters map
*/
public static final String FILTERED_KEY = "isFiltered"; //$NON-NLS-1$
@@ -193,9 +213,9 @@
@SuppressWarnings("unchecked")
private static @Nullable List<Long> transformToLongList(Collection<?> collectionToTransform) {
if (!collectionToTransform.isEmpty()) {
- if (collectionToTransform instanceof List<?> && collectionToTransform.stream().allMatch(e -> e instanceof Long)) {
+ if (collectionToTransform instanceof List<?> && collectionToTransform.stream().allMatch(Long.class::isInstance)) {
return (List<Long>) collectionToTransform;
- } else if (collectionToTransform.stream().allMatch(e -> e instanceof Integer)) {
+ } else if (collectionToTransform.stream().allMatch(Integer.class::isInstance)) {
List<Long> list = new ArrayList<>();
for (Integer element : (List<Integer>) collectionToTransform) {
list.add(element.longValue());
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/markers/ITimeReference.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/markers/ITimeReference.java
new file mode 100644
index 0000000..2034a59
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/markers/ITimeReference.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2021 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.tmf.core.markers;
+
+/**
+ * Time reference interface, allows one to get a time and an index. This is
+ * useful for marker locations or any correlation between gantt charts and other
+ * views.
+ *
+ * @author Matthew Khouzam
+ * @since 7.0
+ */
+public interface ITimeReference {
+
+ /**
+ * Zero reference at index 0 and time 0
+ */
+ ITimeReference ZERO = new TimeReference(0, 0);
+
+ /**
+ * Gets the reference marker time.
+ *
+ * @return the reference marker time
+ */
+ long getTime();
+
+ /**
+ * Gets the reference marker index.
+ *
+ * @return the reference marker index
+ */
+ long getIndex();
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/markers/ITimeReferenceProvider.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/markers/ITimeReferenceProvider.java
new file mode 100644
index 0000000..771c396
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/markers/ITimeReferenceProvider.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2021 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.tmf.core.markers;
+
+import java.util.function.Function;
+
+/**
+ * Marker Reference Provider, allows one to extract a marker time reference from
+ * a given id string
+ *
+ * @author Matthew Khouzam
+ * @since 7.0
+ */
+public interface ITimeReferenceProvider extends Function<String, ITimeReference> {
+
+ /**
+ * Get the reference for the specified reference id
+ *
+ * @param referenceId
+ * the reference id
+ * @return a reference
+ */
+ @Override
+ ITimeReference apply(String referenceId);
+
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/markers/TimeReference.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/markers/TimeReference.java
new file mode 100644
index 0000000..1937b01
--- /dev/null
+++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/markers/TimeReference.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2021 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.tmf.core.markers;
+
+/**
+ * Time reference, contains a timestamp and an index. A simple
+ * {@link ITimeReference} implementation.
+ *
+ * @author Matthew Khouzam
+ * @since 7.0
+ */
+public class TimeReference implements ITimeReference {
+
+ private final long time;
+ private final long index;
+
+ /**
+ * Constructor
+ *
+ * @param time
+ * the reference marker time in time units
+ * @param index
+ * the reference marker index
+ */
+ public TimeReference(long time, long index) {
+ this.time = time;
+ this.index = index;
+ }
+
+ @Override
+ public long getTime() {
+ return time;
+ }
+
+ @Override
+ public long getIndex() {
+ return index;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("[%d, %d]", time, index); //$NON-NLS-1$
+ }
+}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui.tests/src/org/eclipse/tracecompass/tmf/ui/tests/markers/ConfigurableMarkerEventSourceTest.java b/tmf/org.eclipse.tracecompass.tmf.ui.tests/src/org/eclipse/tracecompass/tmf/ui/tests/markers/ConfigurableMarkerEventSourceTest.java
index 3531e37..2e87246 100644
--- a/tmf/org.eclipse.tracecompass.tmf.ui.tests/src/org/eclipse/tracecompass/tmf/ui/tests/markers/ConfigurableMarkerEventSourceTest.java
+++ b/tmf/org.eclipse.tracecompass.tmf.ui.tests/src/org/eclipse/tracecompass/tmf/ui/tests/markers/ConfigurableMarkerEventSourceTest.java
@@ -31,13 +31,13 @@
import org.eclipse.tracecompass.internal.tmf.core.markers.SubMarker.SplitMarker;
import org.eclipse.tracecompass.internal.tmf.core.markers.SubMarker.WeightedMarker;
import org.eclipse.tracecompass.internal.tmf.ui.markers.ConfigurableMarkerEventSource;
+import org.eclipse.tracecompass.tmf.core.markers.ITimeReferenceProvider;
import org.eclipse.tracecompass.tmf.core.tests.shared.TmfTestTrace;
import org.eclipse.tracecompass.tmf.core.trace.AbstractTmfTraceAdapterFactory;
import org.eclipse.tracecompass.tmf.core.trace.ICyclesConverter;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceAdapterManager;
import org.eclipse.tracecompass.tmf.tests.stubs.trace.TmfTraceStub;
-import org.eclipse.tracecompass.tmf.ui.markers.IMarkerReferenceProvider;
import org.eclipse.tracecompass.tmf.ui.markers.PeriodicMarkerEventSource.Reference;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEvent;
import org.junit.After;
@@ -71,10 +71,10 @@
};
return adapterType.cast(adapter);
}
- if (IMarkerReferenceProvider.class.equals(adapterType)) {
- IMarkerReferenceProvider adapter = new IMarkerReferenceProvider() {
+ if (ITimeReferenceProvider.class.equals(adapterType)) {
+ ITimeReferenceProvider adapter = new ITimeReferenceProvider() {
@Override
- public Reference getReference(String referenceId) {
+ public Reference apply(String referenceId) {
if ("ref.c".equals(referenceId)) {
return new Reference(1000L, 0);
}
@@ -90,7 +90,7 @@
public Class<?>[] getAdapterList() {
return new Class[] {
ICyclesConverter.class,
- IMarkerReferenceProvider.class
+ ITimeReferenceProvider.class
};
}
}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Activator.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Activator.java
index 7d89cd0..6779883 100644
--- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Activator.java
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Activator.java
@@ -22,7 +22,6 @@
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.swt.graphics.Image;
-import org.eclipse.tracecompass.internal.tmf.ui.markers.ConfigurableMarkerEventSourceFactory;
import org.eclipse.tracecompass.internal.tmf.ui.markers.LostEventsMarkerEventSourceFactory;
import org.eclipse.tracecompass.internal.tmf.ui.perspectives.TmfPerspectiveManager;
import org.eclipse.tracecompass.internal.tmf.ui.views.TmfAlignmentSynchronizer;
@@ -63,7 +62,6 @@
private TmfEventAdapterFactory fTmfEventAdapterFactory;
private LostEventsMarkerEventSourceFactory fLostEventMarkerEventSourceFactory;
- private ConfigurableMarkerEventSourceFactory fConfigurableMarkerEventSourceFactory;
private IPreferenceStore fCorePreferenceStore;
// ------------------------------------------------------------------------
@@ -109,8 +107,6 @@
Platform.getAdapterManager().registerAdapters(fTmfEventAdapterFactory, ITmfEvent.class);
fLostEventMarkerEventSourceFactory = new LostEventsMarkerEventSourceFactory();
TmfTraceAdapterManager.registerFactory(fLostEventMarkerEventSourceFactory, ITmfTrace.class);
- fConfigurableMarkerEventSourceFactory = new ConfigurableMarkerEventSourceFactory();
- TmfTraceAdapterManager.registerFactory(fConfigurableMarkerEventSourceFactory, ITmfTrace.class);
}
@Override
@@ -125,8 +121,6 @@
Platform.getAdapterManager().unregisterAdapters(fTmfEventAdapterFactory);
TmfTraceAdapterManager.unregisterFactory(fLostEventMarkerEventSourceFactory);
fLostEventMarkerEventSourceFactory.dispose();
- TmfTraceAdapterManager.unregisterFactory(fConfigurableMarkerEventSourceFactory);
- fConfigurableMarkerEventSourceFactory.dispose();
super.stop(context);
}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/markers/ConfigurableMarkerEventSource.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/markers/ConfigurableMarkerEventSource.java
index 5cb0667..ba6f68d 100644
--- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/markers/ConfigurableMarkerEventSource.java
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/markers/ConfigurableMarkerEventSource.java
@@ -17,59 +17,64 @@
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
+import java.util.IllegalFormatException;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
-import java.util.stream.Collectors;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
-import org.eclipse.core.runtime.IAdaptable;
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.swt.graphics.RGB;
import org.eclipse.swt.graphics.RGBA;
-import org.eclipse.tracecompass.internal.tmf.core.markers.IMarkerConstants;
-import org.eclipse.tracecompass.internal.tmf.core.markers.Marker;
-import org.eclipse.tracecompass.internal.tmf.core.markers.Marker.PeriodicMarker;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.Annotation;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.AnnotationCategoriesModel;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.AnnotationModel;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.CustomAnnotationProvider;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.IOutputAnnotationProvider;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.PeriodicAnnotationSource;
import org.eclipse.tracecompass.internal.tmf.core.markers.MarkerSegment;
import org.eclipse.tracecompass.internal.tmf.core.markers.MarkerSet;
import org.eclipse.tracecompass.internal.tmf.core.markers.SubMarker;
-import org.eclipse.tracecompass.internal.tmf.core.markers.SubMarker.SplitMarker;
import org.eclipse.tracecompass.internal.tmf.core.markers.SubMarker.WeightedMarker;
+import org.eclipse.tracecompass.internal.tmf.core.model.filters.FetchParametersUtils;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
+import org.eclipse.tracecompass.tmf.core.model.OutputElementStyle;
+import org.eclipse.tracecompass.tmf.core.model.StyleProperties;
+import org.eclipse.tracecompass.tmf.core.model.filters.TimeQueryFilter;
+import org.eclipse.tracecompass.tmf.core.presentation.RGBAColor;
+import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
import org.eclipse.tracecompass.tmf.core.signal.TmfMarkerEventSourceUpdatedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
import org.eclipse.tracecompass.tmf.core.trace.AbstractTmfTraceAdapterFactory.IDisposableAdapter;
-import org.eclipse.tracecompass.tmf.core.trace.ICyclesConverter;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.eclipse.tracecompass.tmf.ui.colors.ColorUtils;
-import org.eclipse.tracecompass.tmf.ui.markers.IMarkerReferenceProvider;
-import org.eclipse.tracecompass.tmf.ui.markers.PeriodicMarkerEventSource;
-import org.eclipse.tracecompass.tmf.ui.markers.PeriodicMarkerEventSource.Reference;
+import org.eclipse.tracecompass.tmf.ui.colors.RGBAUtil;
+import org.eclipse.tracecompass.tmf.ui.model.StyleManager;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEventSource;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.MarkerEvent;
import com.google.common.collect.Lists;
-import com.google.common.collect.RangeSet;
/**
* Configurable marker event source.
*/
public class ConfigurableMarkerEventSource implements IMarkerEventSource, IDisposableAdapter {
- private static final long NANO_PER_MILLI = 1000000L;
- private static final long NANO_PER_MICRO = 1000L;
private static final int MIN_PERIOD = 5; // in units of resolution intervals
- private static final int ALPHA = 10;
- private static final String COLOR_REGEX = "#[A-Fa-f0-9]{6}"; //$NON-NLS-1$
+ private static final Pattern INDEX_EXTRACTOR = Pattern.compile("(%d+).*"); //$NON-NLS-1$
- private List<IConfigurableMarkerEventSource> fMarkerEventSources;
- private Map<Marker, RGBA> fColors = new HashMap<>();
private final ITmfTrace fTrace;
+ private List<IConfigurableMarkerEventSource> fMarkerEventSources;
+ private CustomAnnotationProvider fProvider;
/**
* Constructor
@@ -78,8 +83,8 @@
* the trace
*/
public ConfigurableMarkerEventSource(ITmfTrace trace) {
- fMarkerEventSources = new ArrayList<>();
fTrace = trace;
+ updateMarkerSet();
TmfSignalManager.register(this);
}
@@ -93,83 +98,117 @@
*
* @param markerSet
* the marker set, or null to clear the configuration
+ * @return The list of marker sources
*/
- public void configure(MarkerSet markerSet) {
- fMarkerEventSources.clear();
- if (markerSet != null) {
- for (Marker marker : markerSet.getMarkers()) {
- configure(marker);
- }
- }
+ public List<IConfigurableMarkerEventSource> configure(MarkerSet markerSet) {
+ fProvider.configure(markerSet);
+ List<@NonNull IConfigurableMarkerEventSource> singletonList = Objects.requireNonNull(Collections.singletonList(new ConfigurableMarkerSource(fProvider)));
+ fMarkerEventSources = singletonList;
+ return singletonList;
}
- private void configure(Marker marker) {
- if (marker instanceof PeriodicMarker) {
- PeriodicMarker periodicMarker = (PeriodicMarker) marker;
- String referenceId = periodicMarker.getReferenceId();
- Reference baseReference = null;
- if (fTrace instanceof IAdaptable && !referenceId.isEmpty()) {
- @Nullable IMarkerReferenceProvider adapter = ((IAdaptable) fTrace).getAdapter(IMarkerReferenceProvider.class);
- if (adapter != null) {
- baseReference = adapter.getReference(referenceId);
+ private class ConfigurableMarkerSource implements IConfigurableMarkerEventSource {
+
+ private final IOutputAnnotationProvider fAnnotationProvider;
+ private boolean fHasError = false;
+
+ public ConfigurableMarkerSource(IOutputAnnotationProvider provider) {
+ fAnnotationProvider = provider;
+ }
+
+ @Override
+ public @NonNull List<@NonNull String> getMarkerCategories() {
+ TimeQueryFilter timeQueryFilter = new TimeQueryFilter(0, Long.MAX_VALUE, 2);
+ List<@NonNull String> categories = new ArrayList<>();
+ Map<@NonNull String, @NonNull Object> fetchParameters = FetchParametersUtils.timeQueryToMap(timeQueryFilter);
+ TmfModelResponse<@NonNull AnnotationCategoriesModel> response = fAnnotationProvider.fetchAnnotationCategories(fetchParameters, new NullProgressMonitor());
+ AnnotationCategoriesModel model = response.getModel();
+ if (model != null) {
+ categories.addAll(model.getAnnotationCategories());
+ }
+ return categories;
+ }
+
+ @SuppressWarnings({"restriction"})
+ @Override
+ public @NonNull List<@NonNull IMarkerEvent> getMarkerList(@NonNull String category, long startTime, long endTime, long resolution, @NonNull IProgressMonitor monitor) {
+ if (startTime >= endTime) {
+ return Collections.emptyList();
+ }
+ TimeQueryFilter filter = new TimeQueryFilter(StateSystemUtils.getTimes(startTime, endTime, resolution));
+ TmfModelResponse<@NonNull AnnotationModel> response = fAnnotationProvider.fetchAnnotations(FetchParametersUtils.timeQueryToMap(filter), monitor);
+ AnnotationModel model = response.getModel();
+ if (model == null) {
+ return Collections.emptyList();
+ }
+ Map<@NonNull String, @NonNull Collection<@NonNull Annotation>> annotationsMap = model.getAnnotations();
+ List<@NonNull IMarkerEvent> markers = new ArrayList<>();
+ Collection<Annotation> collection = annotationsMap.get(category);
+ if (collection != null) {
+ StyleManager sm = StyleManager.empty();
+ for (Annotation annotation : collection) {
+ OutputElementStyle style = annotation.getStyle();
+ if (style != null) {
+ String indexStr = annotation.getLabel();
+ Matcher matcher = INDEX_EXTRACTOR.matcher(indexStr);
+ long index = annotation.getStartTime();
+ if (matcher.matches()) {
+ index = Long.parseLong(matcher.group(1));
+ }
+ boolean isApplicable = true;
+ String label = indexStr;
+ if (fAnnotationProvider instanceof PeriodicAnnotationSource) {
+ PeriodicAnnotationSource source = (PeriodicAnnotationSource) fAnnotationProvider;
+ isApplicable = source.isApplicable(index);
+ if (!fHasError) {
+ try {
+ label = String.format(indexStr, source.getBaseIndex() + index);
+ } catch (IllegalFormatException e) {
+ Activator.getDefault().logError("Cannot format label for periodic marker ", e); //$NON-NLS-1$
+ fHasError = true;
+ }
+ }
+ }
+ if (fAnnotationProvider instanceof CustomAnnotationProvider) {
+ CustomAnnotationProvider customAnnotationProvider = (CustomAnnotationProvider) fAnnotationProvider;
+ Map<String, String> formatters = customAnnotationProvider.getLabel();
+ String format = formatters.get(category);
+ if (!fHasError && format != null) {
+ try {
+ long val = Long.decode(indexStr);
+ label = String.format(format, val);
+ } catch (NumberFormatException | IllegalFormatException e) {
+ Activator.getDefault().logError("Cannot format label for custom marker ", e); //$NON-NLS-1$
+ fHasError = true;
+ }
+ }
+ }
+ if (isApplicable) {
+ annotation = new Annotation(annotation.getTime(), annotation.getDuration(), annotation.getEntryId(), label, style);
+ RGBAColor rgbaColor = sm.getColorStyle(style, StyleProperties.COLOR);
+ if (rgbaColor != null) {
+ RGBA color = RGBAUtil.fromRGBAColor(rgbaColor);
+ // set to false for now
+ MarkerEvent marker = new MarkerEvent(null, annotation.getTime(), annotation.getDuration(), category, color, label, false);
+ markers.add(marker);
+ }
+ }
+ }
}
}
- if (baseReference == null) {
- baseReference = Reference.ZERO;
+
+ return markers;
+ }
+
+ @Override
+ public List<SubMarker> getSubMarkers() {
+ if (fAnnotationProvider instanceof PeriodicAnnotationSource) {
+ return ((PeriodicAnnotationSource) fAnnotationProvider).getMarker().getSubMarkers();
}
- long rollover = periodicMarker.getRange().hasUpperBound() ? (periodicMarker.getRange().upperEndpoint() - periodicMarker.getRange().lowerEndpoint() + 1) : 0;
- RGBA evenColor = getColor(periodicMarker);
- RGBA oddColor = getOddColor(evenColor);
- double period = convertToNanos(periodicMarker.getPeriod(), periodicMarker.getUnit());
- Reference reference = new Reference(baseReference.getTime() + Math.round(convertToNanos(periodicMarker.getOffset(), periodicMarker.getUnit())), baseReference.getIndex());
- ConfigurablePeriodicMarkerEventSource markerEventSource = new ConfigurablePeriodicMarkerEventSource(marker, checkNotNull(periodicMarker.getName()), reference, period, rollover, evenColor, oddColor, false, periodicMarker.getRange().lowerEndpoint(), checkNotNull(periodicMarker.getLabel()), periodicMarker.getIndexRange());
- fMarkerEventSources.add(markerEventSource);
+ return Collections.emptyList();
}
}
- private double convertToNanos(double number, String unit) {
- if (unit.equalsIgnoreCase(IMarkerConstants.MS)) {
- return number * NANO_PER_MILLI;
- } else if (unit.equalsIgnoreCase(IMarkerConstants.US)) {
- return number * NANO_PER_MICRO;
- } else if (unit.equalsIgnoreCase(IMarkerConstants.NS)) {
- return number;
- } else if (unit.equalsIgnoreCase(IMarkerConstants.CYCLES) &&
- fTrace instanceof IAdaptable) {
- ICyclesConverter adapter = ((IAdaptable) fTrace).getAdapter(ICyclesConverter.class);
- if (adapter != null) {
- return adapter.cyclesToNanos((long) number);
- }
- }
- return number;
- }
-
- private @NonNull RGBA getColor(Marker marker) {
- RGBA color = fColors.get(marker);
- if (color == null) {
- color = parseColor(marker.getColor());
- fColors.put(marker, color);
- }
- return color;
- }
-
- private static @NonNull RGBA getOddColor(RGBA color) {
- return new RGBA(color.rgb.red, color.rgb.green, color.rgb.blue, 0);
- }
-
- private static @NonNull RGBA parseColor(String color) {
- RGB rgb = null;
- if (color.matches(COLOR_REGEX)) {
- rgb = ColorUtils.fromHexColor(color);
- } else {
- rgb = ColorUtils.fromX11Color(color);
- if (rgb == null) {
- rgb = new RGB(0, 0, 0);
- }
- }
- return new RGBA(rgb.red, rgb.green, rgb.blue, ALPHA);
- }
-
@Override
public List<String> getMarkerCategories() {
Set<String> categories = new LinkedHashSet<>();
@@ -194,141 +233,40 @@
@Override
public List<IMarkerEvent> getMarkerList(String category, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
- return getMarkerList(startTime, endTime, resolution, monitor).stream()
- .filter((marker) -> marker.getCategory().equals(category))
- .collect(Collectors.toList());
- }
-
- @Override
- public List<IMarkerEvent> getMarkerList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
- @NonNull List<@NonNull IMarkerEvent> markerList = new ArrayList<>();
+ List<@NonNull IMarkerEvent> markerList = new ArrayList<>();
for (IConfigurableMarkerEventSource source : fMarkerEventSources) {
long minDuration = resolution * MIN_PERIOD;
- if (source.getMaxDuration() > minDuration) {
- @NonNull List<@NonNull IMarkerEvent> list = source.getMarkerList(startTime, endTime, resolution, monitor);
- for (IMarkerEvent markerEvent : list) {
- for (SubMarker subMarker : source.getSubMarkers()) {
- getSubMarkerList(subMarker, markerEvent, markerList, startTime, endTime, minDuration);
- }
+ List<@NonNull IMarkerEvent> list = source.getMarkerList(category, startTime, endTime, resolution, monitor);
+ for (IMarkerEvent markerEvent : list) {
+ if (markerEvent.getDuration() > minDuration) {
markerList.add(markerEvent);
}
}
}
- markerList.sort(Comparator.comparingLong(marker -> marker.getTime()));
+ markerList.sort(Comparator.comparingLong(IMarkerEvent::getTime));
return markerList;
}
- private void getSubMarkerList(SubMarker subMarker, IMarkerEvent markerEvent, @NonNull List<@NonNull IMarkerEvent> markerList, long startTime, long endTime, long minDuration) {
- if (subMarker instanceof SplitMarker) {
- getSubMarkerList((SplitMarker) subMarker, markerEvent, markerList, startTime, endTime, minDuration);
- } else if (subMarker instanceof WeightedMarker) {
- getSubMarkerList((WeightedMarker) subMarker, markerEvent, markerList, startTime, endTime, minDuration);
- }
- }
-
- private void getSubMarkerList(SplitMarker splitMarker, IMarkerEvent markerEvent, @NonNull List<@NonNull IMarkerEvent> markerList, long startTime, long endTime, long minDuration) {
- if (markerEvent.getTime() > endTime || markerEvent.getTime() + markerEvent.getDuration() < startTime) {
- return;
- }
- long lower = splitMarker.getRange().lowerEndpoint();
- long upper = splitMarker.getRange().upperEndpoint();
- long segments = upper - lower + 1;
- long start = markerEvent.getTime();
- for (int i = 0; i < segments; i++) {
- long end = markerEvent.getTime() + Math.round((double) (i + 1) / segments * markerEvent.getDuration());
- long duration = end - start;
- long labelIndex = lower + i;
- if (end >= startTime && duration > minDuration && splitMarker.getIndexRange().contains(labelIndex)) {
- RGBA color = (labelIndex & 1) == 0 ? getColor(splitMarker) : getOddColor(getColor(splitMarker));
- IMarkerEvent subMarkerEvent = new MarkerEvent(null, start, end - start, splitMarker.getName(), color, String.format(splitMarker.getLabel(), labelIndex), false);
- for (SubMarker subMarker : splitMarker.getSubMarkers()) {
- getSubMarkerList(subMarker, subMarkerEvent, markerList, startTime, endTime, minDuration);
+ @Override
+ public List<IMarkerEvent> getMarkerList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
+ List<@NonNull IMarkerEvent> markerList = new ArrayList<>();
+ for (IConfigurableMarkerEventSource source : fMarkerEventSources) {
+ long minDuration = resolution * MIN_PERIOD;
+ List<@NonNull IMarkerEvent> list = source.getMarkerList(startTime, endTime, resolution, monitor);
+ for (IMarkerEvent markerEvent : list) {
+ if (markerEvent.getDuration() > minDuration) {
+ markerList.add(markerEvent);
}
- markerList.add(subMarkerEvent);
}
- if (start >= endTime) {
- break;
- }
- start = end;
}
- }
-
- private void getSubMarkerList(WeightedMarker weightedMarker, IMarkerEvent markerEvent, @NonNull List<@NonNull IMarkerEvent> markerList, long startTime, long endTime, long minDuration) {
- if (markerEvent.getTime() > endTime || markerEvent.getTime() + markerEvent.getDuration() < startTime) {
- return;
- }
- long start = markerEvent.getTime();
- long length = 0;
- for (int i = 0; i < weightedMarker.getSegments().size(); i++) {
- MarkerSegment segment = weightedMarker.getSegments().get(i);
- length += segment.getLength();
- long end = markerEvent.getTime() + Math.round((length / (double) weightedMarker.getTotalLength()) * markerEvent.getDuration());
- long duration = end - start;
- if (end >= startTime && duration > minDuration && !segment.getColor().isEmpty()) {
- RGBA color = getColor(segment);
- IMarkerEvent subMarkerEvent = new MarkerEvent(null, start, end - start, weightedMarker.getName(), color, String.format(segment.getLabel(), i), false);
- for (SubMarker subMarker : segment.getSubMarkers()) {
- getSubMarkerList(subMarker, subMarkerEvent, markerList, startTime, endTime, minDuration);
- }
- for (SubMarker subMarker : weightedMarker.getSubMarkers()) {
- getSubMarkerList(subMarker, subMarkerEvent, markerList, startTime, endTime, minDuration);
- }
- markerList.add(subMarkerEvent);
- }
- if (start >= endTime) {
- break;
- }
- start = end;
- }
+ markerList.sort(Comparator.comparingLong(IMarkerEvent::getTime));
+ return markerList;
}
private static interface IConfigurableMarkerEventSource extends IMarkerEventSource {
- double getMaxDuration();
-
public List<SubMarker> getSubMarkers();
}
- private class ConfigurablePeriodicMarkerEventSource extends PeriodicMarkerEventSource implements IConfigurableMarkerEventSource {
-
- private final Marker fMarker;
- private final long fStartIndex;
- private final String fLabel;
- private final RangeSet<Long> fIndexRange;
- private final double fMaxDuration;
-
- public ConfigurablePeriodicMarkerEventSource(Marker marker, @NonNull String category, @NonNull Reference reference, double period, long rollover, @NonNull RGBA evenColor, @NonNull RGBA oddColor, boolean foreground, long startIndex, @NonNull String label, RangeSet<Long> indexRange) {
- super(category, reference, period, rollover, evenColor, oddColor, foreground);
- fMarker = marker;
- fStartIndex = startIndex;
- fLabel = label;
- fIndexRange = indexRange;
- fMaxDuration = period;
- }
-
- @Override
- public @NonNull String getMarkerLabel(long index) {
- return checkNotNull(String.format(fLabel, fStartIndex + index));
- }
-
- @Override
- public boolean isApplicable(long index) {
- if (fIndexRange != null) {
- return fIndexRange.contains(fStartIndex + index);
- }
- return true;
- }
-
- @Override
- public double getMaxDuration() {
- return fMaxDuration;
- }
-
- @Override
- public List<SubMarker> getSubMarkers() {
- return fMarker.getSubMarkers();
- }
- }
-
/**
* A marker event source has been updated
*
@@ -337,6 +275,12 @@
*/
@TmfSignalHandler
public void markerEventSourceUpdated(final TmfMarkerEventSourceUpdatedSignal signal) {
- configure(MarkerUtils.getDefaultMarkerSet());
+ updateMarkerSet();
+ }
+
+ private final void updateMarkerSet() {
+ MarkerSet defaultMarkerSet = MarkerUtils.getDefaultMarkerSet();
+ fProvider = new CustomAnnotationProvider(Objects.requireNonNull(fTrace), defaultMarkerSet);
+ fMarkerEventSources = configure(defaultMarkerSet);
}
}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/markers/IMarkerReferenceProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/markers/IMarkerReferenceProvider.java
index ad05af2..2636a8b 100644
--- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/markers/IMarkerReferenceProvider.java
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/markers/IMarkerReferenceProvider.java
@@ -14,6 +14,7 @@
package org.eclipse.tracecompass.tmf.ui.markers;
+import org.eclipse.tracecompass.tmf.core.markers.ITimeReference;
import org.eclipse.tracecompass.tmf.ui.markers.PeriodicMarkerEventSource.Reference;
/**
@@ -21,8 +22,10 @@
* reference for periodic markers.
*
* @since 3.0
+ * @deprecated, use {@link org.eclipse.tracecompass.tmf.core.markers.ITimeReferenceProvider} instead
*/
-public interface IMarkerReferenceProvider {
+@Deprecated
+public interface IMarkerReferenceProvider extends org.eclipse.tracecompass.tmf.core.markers.ITimeReferenceProvider {
/**
* Get the reference for the specified reference id
@@ -32,4 +35,12 @@
* @return a reference
*/
Reference getReference(String referenceId);
+
+ /**
+ * @since 7.0
+ */
+ @Override
+ default ITimeReference apply(String referenceId) {
+ return getReference(referenceId);
+ }
}
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/markers/PeriodicMarkerEventSource.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/markers/PeriodicMarkerEventSource.java
index 6eca973..ffafc35 100644
--- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/markers/PeriodicMarkerEventSource.java
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/markers/PeriodicMarkerEventSource.java
@@ -18,14 +18,29 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
-import org.apache.commons.lang3.math.Fraction;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.swt.graphics.RGBA;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.Annotation;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.AnnotationModel;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.PeriodicAnnotationSource;
+import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
+import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderParameterUtils;
+import org.eclipse.tracecompass.tmf.core.markers.ITimeReference;
+import org.eclipse.tracecompass.tmf.core.model.OutputElementStyle;
+import org.eclipse.tracecompass.tmf.core.model.StyleProperties;
+import org.eclipse.tracecompass.tmf.core.presentation.RGBAColor;
+import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
+import org.eclipse.tracecompass.tmf.ui.colors.RGBAUtil;
+import org.eclipse.tracecompass.tmf.ui.model.StyleManager;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEventSource;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.MarkerEvent;
@@ -41,7 +56,7 @@
/**
* Reference marker time and index
*/
- public static class Reference {
+ public static class Reference implements ITimeReference {
/** Reference marker index 0 at time 0 */
public static final Reference ZERO = new Reference(0L, 0);
@@ -76,22 +91,12 @@
this.index = index;
}
- /**
- * Gets the reference marker time.
- *
- * @return the reference marker time
- * @since 3.0
- */
+ @Override
public long getTime() {
return time;
}
- /**
- * Gets the reference marker index.
- *
- * @return the reference marker index
- * @since 3.0
- */
+ @Override
public long getIndex() {
return index;
}
@@ -103,14 +108,8 @@
}
private final String fCategory;
- private final Reference fReference;
- private final double fPeriod;
- private final long fPeriodInteger;
- private @Nullable Fraction fPeriodFraction;
- private final long fRollover;
- private final RGBA fColor1;
- private final @Nullable RGBA fColor2;
private final boolean fForeground;
+ private final PeriodicAnnotationSource fSource;
/**
* Constructs a periodic marker event source with line markers at period
@@ -144,8 +143,8 @@
* The markers will have the given category. Periods will be shaded with the
* first and second colors alternatively. The reference defines the marker
* with the given index to be at the specified time. The reference will be
- * shaded with the first color if its index is even, or the second color
- * if it is odd.
+ * shaded with the first color if its index is even, or the second color if
+ * it is odd.
*
* @param category
* the marker category
@@ -167,7 +166,10 @@
this(category, reference, period, rollover, foreground, color1, color2);
}
- /* Private constructor. The order of parameters is changed to make it unique. */
+ /*
+ * Private constructor. The order of parameters is changed to make it
+ * unique.
+ */
private PeriodicMarkerEventSource(String category, Reference reference, double period, long rollover, boolean foreground, RGBA color1, @Nullable RGBA color2) {
if (period <= 0) {
throw new IllegalArgumentException("period cannot be less than or equal to zero"); //$NON-NLS-1$
@@ -175,22 +177,18 @@
if (rollover < 0) {
throw new IllegalArgumentException("rollover cannot be less than zero"); //$NON-NLS-1$
}
+ fSource = new PeriodicAnnotationSource(category, reference.getIndex(), reference.getTime(), period, rollover, Objects.requireNonNull(wrap(color1)), wrap(color2));
fCategory = category;
- fReference = reference;
- fPeriod = period;
- fPeriodInteger = (long) period;
- try {
- fPeriodFraction = Fraction.getFraction(fPeriod - fPeriodInteger);
- } catch (ArithmeticException e) {
- /* can't convert to fraction, use floating-point arithmetic */
- fPeriodFraction = null;
- }
- fRollover = rollover;
- fColor1 = color1;
- fColor2 = color2;
fForeground = foreground;
}
+ private static @Nullable RGBAColor wrap(@Nullable RGBA rgba) {
+ if (rgba == null) {
+ return null;
+ }
+ return new RGBAColor(rgba.rgb.red, rgba.rgb.green, rgba.rgb.blue, rgba.alpha);
+ }
+
@Override
public List<String> getMarkerCategories() {
return Arrays.asList(fCategory);
@@ -201,71 +199,45 @@
if (startTime > endTime) {
return Collections.emptyList();
}
+ StyleManager sm = StyleManager.empty();
List<IMarkerEvent> markers = new ArrayList<>();
- /* Subtract 1.5 periods to ensure previous marker is included */
- long time = startTime - Math.max(Math.round(1.5 * fPeriod), resolution);
- Reference reference = adjustReference(fReference, time);
- IMarkerEvent markerEvent = null;
- while (true) {
- long index = Math.round((time - reference.time) / fPeriod) + reference.index;
- long markerTime = Math.round((index - reference.index) * fPeriod) + reference.time;
- long duration = (fColor2 == null) ? 0 : Math.round((index + 1 - reference.index) * fPeriod) + reference.time - markerTime;
- long labelIndex = index;
- if (fRollover != 0) {
- labelIndex %= fRollover;
- if (labelIndex < 0) {
- labelIndex += fRollover;
+ if (resolution >= Integer.MAX_VALUE) {
+ throw new IllegalArgumentException("Cannot query " + resolution + " times"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ List<Long> times = StateSystemUtils.getTimes(startTime, endTime, resolution);
+ Map<String, Object> query = new HashMap<>();
+ query.put(DataProviderParameterUtils.REQUESTED_TIME_KEY, times);
+ query.put(DataProviderParameterUtils.REQUESTED_MARKER_CATEGORIES_KEY, Collections.singleton(category));
+ TmfModelResponse<AnnotationModel> annotations = fSource.fetchAnnotations(query, monitor);
+ AnnotationModel model = annotations.getModel();
+ if (model == null) {
+ return markers;
+ }
+ Map<String, Collection<Annotation>> annotationsMap = model.getAnnotations();
+
+ Collection<Annotation> collection = annotationsMap.get(category);
+ if (collection != null) {
+ for (Annotation annotation : collection) {
+ OutputElementStyle style = annotation.getStyle();
+ if (style != null) {
+ String indexStr = annotation.getLabel();
+ long index = Long.parseLong(indexStr);
+ if (isApplicable(index)) {
+ String label = getMarkerLabel(index);
+ annotation = new Annotation(annotation.getTime(), annotation.getDuration(), annotation.getEntryId(), label, style);
+ RGBAColor rgbaColor = sm.getColorStyle(style, StyleProperties.COLOR);
+ if (rgbaColor != null) {
+ RGBA color = RGBAUtil.fromRGBAColor(rgbaColor);
+ MarkerEvent marker = new MarkerEvent(null, annotation.getTime(), annotation.getDuration(), category, color, label, fForeground);
+ markers.add(marker);
+ }
+ }
}
}
- /* Add previous marker if current is visible */
- if ((markerTime >= startTime || markerTime + duration > startTime) && markerEvent != null) {
- markers.add(markerEvent);
- }
- if (isApplicable(labelIndex)) {
- RGBA color = (fColor2 == null) ? fColor1 : (index % 2 == 0) ? fColor1 : fColor2;
- markerEvent = new MarkerEvent(null, markerTime, duration, fCategory, color, getMarkerLabel(labelIndex), fForeground);
- } else {
- markerEvent = null;
- }
- if (markerTime > endTime) {
- if (markerEvent != null) {
- /* The next marker out of range is included */
- markers.add(markerEvent);
- }
- break;
- }
- time += Math.max(Math.round(fPeriod), resolution);
}
return markers;
}
- /*
- * Adjust to a reference that is closer to the start time, to avoid rounding
- * errors in floating point calculations with large numbers.
- */
- private Reference adjustReference(Reference baseReference, long time) {
- long offsetIndex = (long) ((time - baseReference.time) / fPeriod);
- long offsetTime = 0;
- Fraction fraction = fPeriodFraction;
- if (fraction != null) {
- /*
- * If period = int num/den, find an offset index that is an exact
- * multiple of den and calculate index * period = (index * int) +
- * (index / den * num), all exact calculations.
- */
- offsetIndex = offsetIndex - offsetIndex % fraction.getDenominator();
- offsetTime = offsetIndex * fPeriodInteger + offsetIndex / fraction.getDenominator() * fraction.getNumerator();
- } else {
- /*
- * Couldn't compute fractional part as fraction, use simple
- * multiplication but with possible rounding error.
- */
- offsetTime = Math.round(offsetIndex * fPeriod);
- }
- Reference reference = new Reference(baseReference.time + offsetTime, baseReference.index + offsetIndex);
- return reference;
- }
-
/**
* Get the marker label for the given marker index.
* <p>
@@ -285,6 +257,9 @@
* This method can be overridden by clients. Returning false will
* essentially filter-out the marker.
*
+ * @apiNote not used as far as we know, this API is not good for moving
+ * logic to core.
+ *
* @param index
* the marker index
* @return true if the marker is applicable
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java
index b0a3108..dbd6ee4 100644
--- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java
@@ -103,6 +103,11 @@
import org.eclipse.tracecompass.common.core.log.TraceCompassLogUtils;
import org.eclipse.tracecompass.common.core.log.TraceCompassLogUtils.FlowScopeLog;
import org.eclipse.tracecompass.common.core.log.TraceCompassLogUtils.FlowScopeLogBuilder;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.Annotation;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.AnnotationCategoriesModel;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.AnnotationModel;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.IAnnotation.AnnotationType;
+import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.IOutputAnnotationProvider;
import org.eclipse.tracecompass.internal.provisional.tmf.core.model.filter.parser.FilterCu;
import org.eclipse.tracecompass.internal.provisional.tmf.core.model.filter.parser.IFilterStrings;
import org.eclipse.tracecompass.internal.provisional.tmf.core.model.filters.TmfFilterAppliedSignal;
@@ -118,9 +123,12 @@
import org.eclipse.tracecompass.internal.tmf.ui.views.ITmfTimeZoomProvider;
import org.eclipse.tracecompass.internal.tmf.ui.views.ITmfZoomToSelectionProvider;
import org.eclipse.tracecompass.internal.tmf.ui.views.timegraph.TimeEventFilterDialog;
+import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
+import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderParameterUtils;
import org.eclipse.tracecompass.tmf.core.model.CoreFilterProperty;
import org.eclipse.tracecompass.tmf.core.model.timegraph.IElementResolver;
import org.eclipse.tracecompass.tmf.core.resources.ITmfMarker;
+import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
import org.eclipse.tracecompass.tmf.core.signal.TmfDataModelSelectedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfMarkerEventSourceUpdatedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
@@ -219,6 +227,61 @@
private static final String HIDE_LABELS_KEY = "hide.labels"; //$NON-NLS-1$
+ private final class AnnotationMarkerEventSource implements IMarkerEventSource {
+ IOutputAnnotationProvider fProvider;
+
+ private AnnotationMarkerEventSource(IOutputAnnotationProvider ap) {
+ fProvider = ap;
+ }
+
+ @Override
+ public @NonNull List<@NonNull IMarkerEvent> getMarkerList(@NonNull String category, long startTime, long endTime, long resolution, @NonNull IProgressMonitor monitor) {
+
+ Map<@NonNull String, @NonNull Object> parameters = new HashMap<>();
+ MarkerSet defaultMarkerSet = MarkerUtils.getDefaultMarkerSet();
+ if (defaultMarkerSet != null) {
+ parameters.put(DataProviderParameterUtils.REQUESTED_MARKER_SET_KEY, defaultMarkerSet.getId());
+ }
+ parameters.put(DataProviderParameterUtils.REQUESTED_TRACE_KEY, fTrace.getHostId());
+ parameters.put(DataProviderParameterUtils.REQUESTED_TIME_KEY, StateSystemUtils.getTimes(startTime, endTime, resolution));
+ TmfModelResponse<@NonNull AnnotationModel> response = fProvider.fetchAnnotations(parameters, new NullProgressMonitor());
+ AnnotationModel model = response.getModel();
+ List<@NonNull IMarkerEvent> traceMarkerList = new ArrayList<>();
+ if (model != null) {
+ for (Entry<String, Collection<Annotation>> entry : model.getAnnotations().entrySet()) {
+ for (Annotation annotation : entry.getValue()) {
+ if (annotation.getType() == AnnotationType.CHART) {
+ if (annotation.getEntryId() != -1) {
+ Activator.getDefault().logWarning("Requesting an annotation with a bound entry. request : " + parameters + ", provider : " + fProvider.getClass().getName() + " annotation: " + annotation); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ // If the annotation entry ID is -1 we want the
+ // marker to span across all entries
+ MarkerEvent markerEvent = new MarkerEvent(annotation, null, entry.getKey(), true);
+ traceMarkerList.add(markerEvent);
+ }
+ }
+ }
+ }
+ return traceMarkerList;
+ }
+
+ @Override
+ public @NonNull List<@NonNull String> getMarkerCategories() {
+ Map<@NonNull String, @NonNull Object> parameters = new HashMap<>();
+ MarkerSet defaultMarkerSet = MarkerUtils.getDefaultMarkerSet();
+ if (defaultMarkerSet != null) {
+ parameters.put(DataProviderParameterUtils.REQUESTED_MARKER_SET_KEY, defaultMarkerSet.getId());
+ }
+ parameters.put(DataProviderParameterUtils.REQUESTED_TRACE_KEY, fTrace.getHostId());
+ TmfModelResponse<@NonNull AnnotationCategoriesModel> cats = fProvider.fetchAnnotationCategories(parameters, new NullProgressMonitor());
+ AnnotationCategoriesModel model = cats.getModel();
+ if (model != null) {
+ return model.getAnnotationCategories();
+ }
+ return Collections.emptyList();
+ }
+ }
+
/**
* Redraw state enum
*/
@@ -1854,7 +1917,11 @@
break;
}
List<@NonNull IMarkerEventSource> adapters = TmfTraceAdapterManager.getAdapters(trace, IMarkerEventSource.class);
+ List<@NonNull IOutputAnnotationProvider> providers = TmfTraceAdapterManager.getAdapters(trace, IOutputAnnotationProvider.class);
markerEventSources.addAll(adapters);
+ for (IOutputAnnotationProvider ap : providers) {
+ markerEventSources.add(new AnnotationMarkerEventSource(ap));
+ }
Job buildJob = new Job(getTitle() + Messages.AbstractTimeGraphView_BuildJob) {
@Override
diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/BaseDataProviderTimeGraphView.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/BaseDataProviderTimeGraphView.java
index 1e8e380..460be3f 100644
--- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/BaseDataProviderTimeGraphView.java
+++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/BaseDataProviderTimeGraphView.java
@@ -44,7 +44,9 @@
import org.eclipse.tracecompass.internal.provisional.tmf.core.model.annotations.IOutputAnnotationProvider;
import org.eclipse.tracecompass.internal.provisional.tmf.ui.widgets.ViewFilterDialog;
import org.eclipse.tracecompass.internal.provisional.tmf.ui.widgets.timegraph.BaseDataProviderTimeGraphPresentationProvider;
+import org.eclipse.tracecompass.internal.tmf.core.markers.MarkerSet;
import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.markers.MarkerUtils;
import org.eclipse.tracecompass.internal.tmf.ui.views.timegraph.Messages;
import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
import org.eclipse.tracecompass.tmf.core.TmfStrings;
@@ -437,7 +439,7 @@
if (zoomStartTime <= entry.getEndTime() && zoomEndTime >= entry.getStartTime() && entry.hasTimeEvents()) {
synchronized (fEntries) {
if (!fEntryIds.isEmpty()) {
- fEntryIds.row(entry).forEach((provider, modelId) -> providersToModelIds.put(provider, modelId));
+ fEntryIds.row(entry).forEach(providersToModelIds::put);
} else {
ITimeGraphDataProvider<? extends TimeGraphEntryModel> provider = getProvider(entry);
if (provider != null) {
@@ -706,7 +708,20 @@
* @since 5.2
*/
protected @NonNull Map<@NonNull String, @NonNull Object> getFetchAnnotationCategoriesParameters() {
- return new HashMap<>();
+ HashMap<@NonNull String, @NonNull Object> categoriesParameters = new HashMap<>();
+ putMarkerSetParameters(categoriesParameters, getTrace());
+ return categoriesParameters;
+ }
+
+ private static void putMarkerSetParameters(Map<@NonNull String, @NonNull Object> parameters, ITmfTrace trace) {
+ MarkerSet markerSet = MarkerUtils.getDefaultMarkerSet();
+ if (markerSet != null) {
+ String markerSetID = markerSet.getId();
+ if (markerSetID != null) {
+ parameters.put(DataProviderParameterUtils.REQUESTED_MARKER_SET_KEY, markerSetID);
+ parameters.put(DataProviderParameterUtils.REQUESTED_TRACE_KEY, trace.getHostId());
+ }
+ }
}
/**
@@ -720,9 +735,10 @@
* @since 5.2
*/
protected @NonNull Map<@NonNull String, @NonNull Object> getFetchAnnotationsParameters(@NonNull List<Long> times, @NonNull Collection<Long> items) {
- @NonNull Map<@NonNull String, @NonNull Object> parameters = new HashMap<>();
+ Map<@NonNull String, @NonNull Object> parameters = new HashMap<>();
parameters.put(DataProviderParameterUtils.REQUESTED_TIME_KEY, times);
parameters.put(DataProviderParameterUtils.REQUESTED_ITEMS_KEY, items);
+ putMarkerSetParameters(parameters, getTrace());
return parameters;
}