blob: b556bb419e3e31ae9de6f1048b0a3a5ee792fb0c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2018 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Patrick Tasse - Initial API and implementation
*******************************************************************************/
package org.eclipse.tracecompass.internal.tmf.ui.markers;
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.swt.graphics.RGBA;
import org.eclipse.tracecompass.internal.tmf.ui.Messages;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
import org.eclipse.tracecompass.tmf.core.statistics.TmfStateStatistics.Attributes;
import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsEventTypesModule;
import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsModule;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
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;
/**
* Marker event source for lost events.
*/
public class LostEventsMarkerEventSource implements IMarkerEventSource {
private static final @NonNull String LOST_EVENTS = checkNotNull(Messages.MarkerEvent_LostEvents);
private static final RGBA COLOR = new RGBA(255, 0, 0, 50);
private final @NonNull ITmfTrace fTrace;
private long[] fLastRequest;
private @NonNull List<@NonNull IMarkerEvent> fLastMarkers = Collections.emptyList();
/**
* Constructor.
*
* @param trace
* the trace
*/
public LostEventsMarkerEventSource(@NonNull ITmfTrace trace) {
fTrace = trace;
}
@Override
public @NonNull List<@NonNull String> getMarkerCategories() {
return Arrays.asList(LOST_EVENTS);
}
@Override
public synchronized @NonNull List<@NonNull IMarkerEvent> getMarkerList(@NonNull String category, long startTime, long endTime, long resolution, @NonNull IProgressMonitor monitor) {
if (!category.equals(LOST_EVENTS)) {
return Collections.emptyList();
}
ITmfStateSystem ss = getStateSystem();
if (ss == null) {
return Collections.emptyList();
}
int lostEventsQuark = getLostEventsQuark(ss);
if (lostEventsQuark == -1) {
return Collections.emptyList();
}
long[] request = new long[] { startTime, endTime, resolution, ss.getCurrentEndTime() };
if (Arrays.equals(request, fLastRequest)) {
return fLastMarkers;
}
List<@NonNull IMarkerEvent> markers = new ArrayList<>();
try {
long start = Math.max(startTime, ss.getStartTime());
long end = Math.min(endTime, ss.getCurrentEndTime());
if (start <= end) {
/* Update start to ensure that the previous marker is included. */
start = Math.max(start - 1, ss.getStartTime());
/* Update end to ensure that the next marker is included. */
long nextStartTime = ss.querySingleState(end, lostEventsQuark).getEndTime() + 1;
end = Math.min(nextStartTime, ss.getCurrentEndTime());
List<ITmfStateInterval> intervals = StateSystemUtils.queryHistoryRange(ss, lostEventsQuark, start, end, resolution, monitor);
if (monitor.isCanceled()) {
return Collections.emptyList();
}
for (ITmfStateInterval interval : intervals) {
if (interval.getStateValue().isNull()) {
continue;
}
long lostEventsStartTime = interval.getStartTime();
/*
* The end time of the lost events range is the value of the
* attribute, not the end time of the interval.
*/
long lostEventsEndTime = interval.getStateValue().unboxLong();
long duration = lostEventsEndTime - lostEventsStartTime;
IMarkerEvent marker = new MarkerEvent(null, lostEventsStartTime, duration, LOST_EVENTS, COLOR, null, false);
markers.add(marker);
}
}
} catch (AttributeNotFoundException | StateSystemDisposedException e) {
/* ignored */
}
fLastRequest = request;
fLastMarkers = Collections.unmodifiableList(markers);
return fLastMarkers;
}
private ITmfStateSystem getStateSystem() {
TmfStatisticsModule module = TmfTraceUtils.getAnalysisModuleOfClass(fTrace, TmfStatisticsModule.class, TmfStatisticsModule.ID);
if (module == null) {
return null;
}
return module.getStateSystem(TmfStatisticsEventTypesModule.ID);
}
private static int getLostEventsQuark(ITmfStateSystem ss) {
try {
return ss.getQuarkAbsolute(Attributes.LOST_EVENTS);
} catch (AttributeNotFoundException e) {
return -1;
}
}
}