Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-Vendor: %Bundle-Vendor
-Bundle-Version: 1.0.0.qualifier
+Bundle-Version: 1.1.0.qualifier
Bundle-Localization: plugin
Bundle-SymbolicName: org.eclipse.tracecompass.analysis.os.linux.core;singleton:=true
Bundle-Activator: org.eclipse.tracecompass.internal.analysis.os.linux.core.Activator
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.resources,
org.eclipse.tracecompass.common.core,
- org.eclipse.tracecompass.tmf.core
-Import-Package: com.google.common.collect,
- com.google.common.hash;version="15.0.0"
+ org.eclipse.tracecompass.tmf.core,
+ org.eclipse.tracecompass.segmentstore.core
+Import-Package: com.google.common.base,
+ com.google.common.collect,
+ com.google.common.hash
Export-Package: org.eclipse.tracecompass.analysis.os.linux.core.cpuusage,
org.eclipse.tracecompass.analysis.os.linux.core.event.aspect,
org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis,
+ org.eclipse.tracecompass.analysis.os.linux.core.latency,
org.eclipse.tracecompass.analysis.os.linux.core.model,
org.eclipse.tracecompass.analysis.os.linux.core.trace,
org.eclipse.tracecompass.internal.analysis.os.linux.core;x-internal:=true,
analysis.linuxkernel = Linux Kernel Analysis
analysis.cpuusage = CPU usage
+analysis.latency = Latency Analysis
class="org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace">
</tracetype>
</module>
+ <module
+ analysis_module="org.eclipse.tracecompass.analysis.os.linux.core.latency.LatencyAnalysis"
+ automatic="false"
+ id="org.eclipse.tracecompass.analysis.os.linux.latency"
+ name="%analysis.latency">
+ <tracetype
+ applies="true"
+ class="org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace">
+ </tracetype>
+ </module>
</extension>
</plugin>
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (C) 2011, Red Hat, Inc.
+ Copyright (C) 2011, 2015 Red Hat, Inc. and others
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
<artifactId>org.eclipse.tracecompass.analysis.os.linux.core</artifactId>
<groupId>org.eclipse.tracecompass</groupId>
- <version>1.0.0-SNAPSHOT</version>
+ <version>1.1.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
<name>Trace Compass Linux Kernel Analysis Core Plug-in</name>
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 EfficiOS Inc., Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.analysis.os.linux.core.latency;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelTidAspect;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
+import org.eclipse.tracecompass.segmentstore.core.treemap.TreeMapStore;
+import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
+import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
+import org.eclipse.tracecompass.tmf.core.request.TmfEventRequest;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+
+/**
+ * @author Alexandre Montplaisir
+ * @since 1.1
+ */
+public class LatencyAnalysis extends TmfAbstractAnalysisModule {
+
+ /**
+ * The ID of this analysis
+ */
+ public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.latency"; //$NON-NLS-1$
+
+ private static final String DATA_FILENAME = "latency-analysis.dat"; //$NON-NLS-1$
+
+ private @Nullable ISegmentStore<ISegment> fSystemCalls;
+
+ private final Set<LatencyAnalysisListener> fListeners = new HashSet<>();
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+ /**
+ * Listener for the viewers
+ *
+ * @param listener
+ * listener for each type of viewer
+ */
+ public void addListener(LatencyAnalysisListener listener) {
+ fListeners.add(listener);
+ }
+
+ @Override
+ protected boolean executeAnalysis(IProgressMonitor monitor) throws TmfAnalysisException {
+ IKernelTrace trace = checkNotNull((IKernelTrace) getTrace());
+ IKernelAnalysisEventLayout layout = trace.getKernelEventLayout();
+
+ /* See if the data file already exists on disk */
+ String dir = TmfTraceManager.getSupplementaryFileDir(trace);
+ final Path file = Paths.get(dir, DATA_FILENAME);
+
+ if (Files.exists(file)) {
+ /* Attempt to read the existing file */
+ try (ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(file))) {
+ @SuppressWarnings("unchecked")
+ ISegmentStore<ISegment> syscalls = (ISegmentStore<ISegment>) ois.readObject();
+ fSystemCalls = syscalls;
+ return true;
+ } catch (IOException | ClassNotFoundException | ClassCastException e) {
+ /*
+ * We did not manage to read the file successfully, we will just
+ * fall-through to rebuild a new one.
+ */
+ try {
+ Files.delete(file);
+ } catch (IOException e1) {
+ }
+ }
+ }
+
+ ISegmentStore<ISegment> syscalls = new TreeMapStore<>();
+ ITmfEventRequest req = new LatencyAnalysisRequest(layout, syscalls);
+ trace.sendRequest(req);
+ try {
+ req.waitForCompletion();
+ } catch (InterruptedException e) {
+ }
+ /* The request will fill 'syscalls' */
+ fSystemCalls = syscalls;
+
+ /* Serialize the collections to disk for future usage */
+ try (ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(file))) {
+ oos.writeObject(syscalls);
+ } catch (IOException e) {
+ /* Didn't work, oh well. We will just re-read the trace next time */
+ }
+
+ for (LatencyAnalysisListener listener : fListeners) {
+ listener.onComplete(this, syscalls);
+ }
+
+ return true;
+ }
+
+ @Override
+ protected void canceling() {
+
+ }
+
+ /**
+ * @return Results from the analysis in a ISegmentStore
+ */
+ public @Nullable ISegmentStore<ISegment> getResults() {
+ return fSystemCalls;
+ }
+
+ private static class LatencyAnalysisRequest extends TmfEventRequest {
+
+ private final IKernelAnalysisEventLayout fLayout;
+ private final ISegmentStore<ISegment> fFullSyscalls;
+ private final Map<Integer, SystemCall.InitialInfo> fOngoingSystemCalls = new HashMap<>();
+
+ public LatencyAnalysisRequest(IKernelAnalysisEventLayout layout, ISegmentStore<ISegment> syscalls) {
+ super(ITmfEvent.class, 0, ITmfEventRequest.ALL_DATA, ExecutionType.BACKGROUND);
+ fLayout = layout;
+ /*
+ * We do NOT make a copy here! We want to modify the list that was
+ * passed in parameter.
+ */
+ fFullSyscalls = syscalls;
+ }
+
+ @Override
+ public void handleData(final ITmfEvent event) {
+ super.handleData(event);
+ final String eventName = event.getType().getName();
+
+ if (eventName.startsWith(fLayout.eventSyscallEntryPrefix()) ||
+ eventName.startsWith(fLayout.eventCompatSyscallEntryPrefix())) {
+ /* This is a system call entry event */
+
+ Integer tid = KernelTidAspect.INSTANCE.resolve(event);
+ if (tid == null) {
+ // no information on this event/trace ?
+ return;
+ }
+
+ /* Record the event's data into the intial system call info */
+ // String syscallName = fLayout.getSyscallNameFromEvent(event);
+ long startTime = event.getTimestamp().getValue();
+ String syscallName = eventName.substring(fLayout.eventSyscallEntryPrefix().length());
+ FluentIterable<String> argNames = FluentIterable.from(event.getContent().getFieldNames());
+ Map<String, String> args = argNames.toMap(new Function<String, String>() {
+ @Override
+ public String apply(@Nullable String input) {
+ return checkNotNull(event.getContent().getField(input).getValue().toString());
+ }
+ });
+ SystemCall.InitialInfo newSysCall = new SystemCall.InitialInfo(startTime, NonNullUtils.checkNotNull(syscallName), NonNullUtils.checkNotNull(args));
+ fOngoingSystemCalls.put(tid, newSysCall);
+
+ } else if (eventName.startsWith(fLayout.eventSyscallExitPrefix())) {
+ /* This is a system call exit event */
+
+ Integer tid = KernelTidAspect.INSTANCE.resolve(event);
+ if (tid == null) {
+ return;
+ }
+
+ SystemCall.InitialInfo info = fOngoingSystemCalls.remove(tid);
+ if (info == null) {
+ /*
+ * We have not seen the entry event corresponding to this
+ * exit (lost event, or before start of trace).
+ */
+ return;
+ }
+
+ long endTime = event.getTimestamp().getValue();
+ int ret = ((Long) event.getContent().getField("ret").getValue()).intValue(); //$NON-NLS-1$
+ ISegment syscall = new SystemCall(info, endTime, ret);
+ fFullSyscalls.addElement(syscall);
+ }
+ }
+
+ @Override
+ public void handleCompleted() {
+ fOngoingSystemCalls.clear();
+ }
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.analysis.os.linux.core.latency;
+
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
+
+/**
+ * End of latency analysis listener for latency viewers
+ *
+ * @author France Lapointe Nguyen
+ * @since 1.1
+ */
+public interface LatencyAnalysisListener {
+
+ /**
+ * Called at the end of the latency analysis
+ *
+ * @param activeAnalysis
+ * latency analysis that is running
+ *
+ * @param data
+ * results of the latency analysis
+ */
+ void onComplete(LatencyAnalysis activeAnalysis, ISegmentStore<ISegment> data);
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.analysis.os.linux.core.latency;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Ordering;
+
+/**
+ * A linux kernel system call, represented as an {@link ISegment}.
+ *
+ * @author Alexandre Montplaisir
+ * @since 1.1
+ */
+public class SystemCall implements ISegment {
+
+ private static final long serialVersionUID = 1554494342105208730L;
+
+ private static final Comparator<ISegment> COMPARATOR = checkNotNull(Ordering
+ .from(SegmentComparators.INTERVAL_START_COMPARATOR)
+ .compound(SegmentComparators.INTERVAL_END_COMPARATOR)
+ /* Kind of lazy, but should work! */
+ .compound(Ordering.usingToString()));
+
+ /**
+ * The subset of information that is available from the syscall entry event.
+ */
+ public static class InitialInfo implements Serializable {
+
+ private static final long serialVersionUID = -5009710718804983721L;
+
+ private final long fStartTime;
+ private final String fName;
+ private final Map<String, String> fArgs;
+
+ /**
+ * @param startTime
+ * Start time of the system call
+ * @param name
+ * Name of the system call
+ * @param arguments
+ * Arguments of the system call
+ */
+ public InitialInfo(
+ long startTime,
+ String name,
+ Map<String, String> arguments) {
+ fStartTime = startTime;
+ fName = name;
+ fArgs = NonNullUtils.checkNotNull(ImmutableMap.copyOf(arguments));
+ }
+ }
+
+ private final InitialInfo fInfo;
+ private final long fEndTime;
+ private final int fRet;
+ private final transient long fDuration;
+
+ /**
+ * @param info
+ * Initial information of the system call
+ * @param endTime
+ * End time of the system call
+ * @param ret
+ * Return value of the system call
+ */
+ public SystemCall(
+ InitialInfo info,
+ long endTime,
+ int ret) {
+ fInfo = info;
+ fEndTime = endTime;
+ fRet = ret;
+ fDuration = fEndTime - fInfo.fStartTime;
+ }
+
+ @Override
+ public long getStart() {
+ return fInfo.fStartTime;
+ }
+
+ @Override
+ public long getEnd() {
+ return fEndTime;
+ }
+
+ @Override
+ public long getLength() {
+ return fDuration;
+ }
+
+ /**
+ * Get the name of the system call
+ *
+ * @return Name
+ */
+ public String getName() {
+ return fInfo.fName;
+ }
+
+ /**
+ * Get the arguments of the system call
+ *
+ * @return Map of the arguments
+ */
+ public Map<String, String> getArguments() {
+ return fInfo.fArgs;
+ }
+
+ /**
+ * Get the return value of the system call
+ *
+ * @return Return value
+ */
+ public int getReturnValue() {
+ return fRet;
+ }
+
+
+ @Override
+ public int compareTo(@Nullable ISegment o) {
+ if (o == null) {
+ throw new IllegalArgumentException();
+ }
+ return COMPARATOR.compare(this, o);
+ }
+
+ @Override
+ public String toString() {
+ return "Start Time = " + getStart() + //$NON-NLS-1$
+ "; End Time = " + getEnd() + //$NON-NLS-1$
+ "; Duration = " + getLength() + //$NON-NLS-1$
+ "; Name = " + getName() + //$NON-NLS-1$
+ "; Args = " + getArguments().toString() + //$NON-NLS-1$
+ "; Return = " + getReturnValue(); //$NON-NLS-1$
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.analysis.os.linux.core.latency;
org.eclipse.tracecompass.analysis.os.linux.core,
org.eclipse.tracecompass.tmf.core,
org.eclipse.tracecompass.tmf.ui,
- org.eclipse.tracecompass.tmf.ctf.core
+ org.eclipse.tracecompass.tmf.ctf.core,
+ org.eclipse.tracecompass.segmentstore.core
Import-Package: com.google.common.collect
Export-Package: org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow,
org.eclipse.tracecompass.analysis.os.linux.ui.views.cpuusage,
org.eclipse.tracecompass.analysis.os.linux.ui.views.resources,
- org.eclipse.tracecompass.internal.analysis.os.linux.ui;x-internal:=true
+ org.eclipse.tracecompass.internal.analysis.os.linux.ui;x-internal:=true,
+ org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;x-internal:=true
controlflow.view.name = Control Flow
resources.view.name = Resources
cpuusage.view.name = CPU Usage
+latency.view.name = Latency Analysis
\ No newline at end of file
name="%cpuusage.view.name"
restorable="true">
</view>
+ <view
+ allowMultiple="false"
+ category="org.eclipse.linuxtools.lttng2.ui.views.category"
+ class="org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.LatencyView"
+ id="org.eclipse.tracecompass.analysis.os.linux.views.latency"
+ name="%latency.view.name"
+ restorable="true">
+ </view>
</extension>
<extension
point="org.eclipse.linuxtools.tmf.core.analysis">
class="org.eclipse.tracecompass.analysis.os.linux.core.cpuusage.KernelCpuUsageAnalysis">
</analysisModuleClass>
</output>
+ <output
+ class="org.eclipse.tracecompass.tmf.ui.analysis.TmfAnalysisViewOutput"
+ id="org.eclipse.tracecompass.analysis.os.linux.views.latency">
+ <analysisModuleClass
+ class="org.eclipse.tracecompass.analysis.os.linux.core.latency.LatencyAnalysis">
+ </analysisModuleClass>
+ </output>
</extension>
</plugin>
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * France Lapointe Nguyen - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
+import org.eclipse.tracecompass.tmf.ui.viewers.table.ISortingLazyContentProvider;
+
+import com.google.common.collect.Iterables;
+
+/**
+ * Content provider for the latency table viewers.
+ *
+ * @author France Lapointe Nguyen
+ */
+public class LatencyContentProvider implements ISortingLazyContentProvider {
+
+ /**
+ * Array of all the segments in the segment store of the current trace
+ */
+ private @Nullable ISegment[] fSegmentArray = null;
+
+ /**
+ * Table viewer of the latency table viewer
+ */
+ private @Nullable TableViewer fTableViewer = null;
+
+ /**
+ * Segment comparator
+ */
+ private @Nullable Comparator<ISegment> fComparator = null;
+
+ @Override
+ public void updateElement(int index) {
+ final TableViewer tableViewer = fTableViewer;
+ final ISegment[] segmentArray = fSegmentArray;
+ if (tableViewer != null && segmentArray != null) {
+ tableViewer.replace(segmentArray[index], index);
+ }
+ }
+
+ @Override
+ public void dispose() {
+ fSegmentArray = null;
+ fTableViewer = null;
+ fComparator = null;
+ }
+
+ @Override
+ public void inputChanged(@Nullable Viewer viewer, @Nullable Object oldInput, @Nullable Object newInput) {
+ fTableViewer = (TableViewer) viewer;
+ if (newInput instanceof ISegmentStore<?>) {
+ ISegmentStore<?> segmentStore = (ISegmentStore<?>) newInput;
+ fSegmentArray = Iterables.toArray(segmentStore, ISegment.class);
+ if (fComparator != null) {
+ Arrays.sort(fSegmentArray, fComparator);
+ }
+ } else {
+ fSegmentArray = null;
+ }
+ }
+
+ @Override
+ public void setSortOrder(@Nullable Comparator<?> comparator) {
+ if (comparator == null) {
+ return;
+ }
+ if (fSegmentArray == null) {
+ return;
+ }
+ final TableViewer tableViewer = fTableViewer;
+ if (tableViewer == null) {
+ return;
+ }
+ fComparator = (Comparator<ISegment>) comparator;
+ Arrays.sort(fSegmentArray, fComparator);
+ tableViewer.refresh();
+ }
+
+ /**
+ * Get the segment count
+ *
+ * @return the segment count
+ */
+ public int getSegmentCount() {
+ ISegment[] segmentArray = fSegmentArray;
+ return (segmentArray == null ? 0 : segmentArray.length);
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * France Lapointe Nguyen - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.tracecompass.analysis.os.linux.core.latency.LatencyAnalysis;
+import org.eclipse.tracecompass.analysis.os.linux.core.latency.LatencyAnalysisListener;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
+import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
+import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.ui.viewers.table.TmfSimpleTableViewer;
+
+/**
+ * Displays the latency analysis data in a column table
+ *
+ * @author France Lapointe Nguyen
+ */
+public class LatencyTableViewer extends TmfSimpleTableViewer {
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ /**
+ * Abstract class for the column label provider for the latency analysis
+ * table viewer
+ */
+ private abstract class LatencyTableColumnLabelProvider extends ColumnLabelProvider {
+
+ @Override
+ public String getText(@Nullable Object input) {
+ if (!(input instanceof ISegment)) {
+ /* Doubles as a null check */
+ return ""; //$NON-NLS-1$
+ }
+ return getTextFoITimeRange((ISegment) input);
+ }
+
+ public abstract String getTextFoITimeRange(ISegment input);
+ }
+
+ /**
+ * Listener to update the model with the latency analysis results once the
+ * latency analysis is fully completed
+ */
+ private final class LatencyListener implements LatencyAnalysisListener {
+ @Override
+ public void onComplete(LatencyAnalysis activeAnalysis, ISegmentStore<ISegment> data) {
+ // Check if the active trace was changed while the analysis was
+ // running
+ if (activeAnalysis.equals(fAnalysisModule)) {
+ updateModel(data);
+ }
+ }
+ }
+
+ /**
+ * Listener to select a range in other viewers when a cell of the latency
+ * table view is selected
+ */
+ private class LatencyTableSelectionListener extends SelectionAdapter {
+ @Override
+ public void widgetSelected(@Nullable SelectionEvent e) {
+ ISegment selectedSegment = ((ISegment) NonNullUtils.checkNotNull(e).item.getData());
+ ITmfTimestamp start = new TmfNanoTimestamp(selectedSegment.getStart());
+ ITmfTimestamp end = new TmfNanoTimestamp(selectedSegment.getEnd());
+ TmfSignalManager.dispatchSignal(new TmfSelectionRangeUpdatedSignal(LatencyTableViewer.this, start, end));
+ }
+ }
+
+ /**
+ * Current latency analysis module
+ */
+ private @Nullable LatencyAnalysis fAnalysisModule = null;
+
+ /**
+ * Latency analysis completion listener
+ */
+ private LatencyListener fListener;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * @param tableViewer
+ * Table viewer of the view
+ */
+ public LatencyTableViewer(TableViewer tableViewer) {
+ super(tableViewer);
+ // Sort order of the content provider is by start time by default
+ getTableViewer().setContentProvider(new LatencyContentProvider());
+ ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
+ if (trace != null) {
+ fAnalysisModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, LatencyAnalysis.class, LatencyAnalysis.ID);
+ }
+ createColumns();
+ getTableViewer().getTable().addSelectionListener(new LatencyTableSelectionListener());
+ fListener = new LatencyListener();
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ /**
+ * Create columns for start time, end time and duration
+ */
+ private void createColumns() {
+ createColumn(Messages.LatencyTableViewer_startTime, new LatencyTableColumnLabelProvider() {
+ @Override
+ public String getTextFoITimeRange(ISegment input) {
+ return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getStart()));
+ }
+ }, SegmentComparators.INTERVAL_START_COMPARATOR);
+
+ createColumn(Messages.LatencyTableViewer_endTime, new LatencyTableColumnLabelProvider() {
+ @Override
+ public String getTextFoITimeRange(ISegment input) {
+ return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getEnd()));
+ }
+ }, SegmentComparators.INTERVAL_END_COMPARATOR);
+
+ createColumn(Messages.LatencyTableViewer_duration, new LatencyTableColumnLabelProvider() {
+ @Override
+ public String getTextFoITimeRange(ISegment input) {
+ return NonNullUtils.nullToEmptyString(Long.toString(input.getLength()));
+ }
+ }, SegmentComparators.INTERVAL_LENGTH_COMPARATOR);
+ }
+
+ /**
+ * Update the data in the table viewer
+ *
+ * @param dataInput
+ * New data input
+ */
+ public void updateModel(final @Nullable ISegmentStore<ISegment> dataInput) {
+ final TableViewer tableViewer = getTableViewer();
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (!tableViewer.getTable().isDisposed()) {
+ // Go to the top of the table
+ tableViewer.getTable().setTopIndex(0);
+ // Reset selected row
+ tableViewer.setSelection(StructuredSelection.EMPTY);
+ if (dataInput == null) {
+ tableViewer.setInput(null);
+ tableViewer.setItemCount(0);
+ return;
+ }
+ tableViewer.setInput(dataInput);
+ LatencyContentProvider latencyContentProvider = (LatencyContentProvider) getTableViewer().getContentProvider();
+ tableViewer.setItemCount(latencyContentProvider.getSegmentCount());
+ }
+ }
+ });
+ }
+
+ /**
+ * Set the data into the viewer. Will update model is analysis is completed
+ * or run analysis if not completed
+ *
+ * @param analysis
+ * Latency analysis module
+ */
+ public void setData(@Nullable LatencyAnalysis analysis) {
+ // Set the current latency analysis module
+ fAnalysisModule = analysis;
+ if (analysis == null) {
+ updateModel(null);
+ return;
+ }
+ ISegmentStore<ISegment> results = analysis.getResults();
+ // If results are not null, then analysis is completed and model can be
+ // updated
+ if (results != null) {
+ updateModel(results);
+ return;
+ }
+ // If results are null, then add completion listener and run analysis
+ updateModel(null);
+ analysis.addListener(fListener);
+ analysis.schedule();
+ }
+
+ // ------------------------------------------------------------------------
+ // Getters
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get current latency analysis module
+ *
+ * @return current latency analysis module
+ */
+ public @Nullable LatencyAnalysis getAnalysisModule() {
+ return fAnalysisModule;
+ }
+
+ // ------------------------------------------------------------------------
+ // Signal handlers
+ // ------------------------------------------------------------------------
+
+ /**
+ * Trace selected handler
+ *
+ * @param signal
+ * Different opened trace (on which latency analysis as already
+ * been performed) has been selected
+ */
+ @TmfSignalHandler
+ public void traceSelected(TmfTraceSelectedSignal signal) {
+ ITmfTrace trace = signal.getTrace();
+ if (trace != null) {
+ setData(TmfTraceUtils.getAnalysisModuleOfClass(trace, LatencyAnalysis.class, LatencyAnalysis.ID));
+ }
+ }
+
+ /**
+ * Trace opened handler
+ *
+ * @param signal
+ * New trace (on which latency analysis has not been performed)
+ * is opened
+ */
+ @TmfSignalHandler
+ public void traceOpened(TmfTraceOpenedSignal signal) {
+ ITmfTrace trace = signal.getTrace();
+ if (trace != null) {
+ setData(TmfTraceUtils.getAnalysisModuleOfClass(trace, LatencyAnalysis.class, LatencyAnalysis.ID));
+ }
+ }
+
+ /**
+ * Trace closed handler
+ *
+ * @param signal
+ * Last opened trace was closed
+ */
+ @TmfSignalHandler
+ public void traceClosed(TmfTraceClosedSignal signal) {
+ // Check if there is no more opened trace
+ if (TmfTraceManager.getInstance().getActiveTrace() == null) {
+ if (!getTableViewer().getTable().isDisposed()) {
+ getTableViewer().setInput(null);
+ refresh();
+ }
+ }
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * France Lapointe Nguyen - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.tracecompass.tmf.ui.views.TmfView;
+
+/**
+ * View for the latency analysis
+ *
+ * @author France Lapointe Nguyen
+ */
+public class LatencyView extends TmfView {
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ /** The view's ID */
+ public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.latency"; //$NON-NLS-1$
+
+ private @Nullable LatencyTableViewer fTableViewer;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor
+ */
+ public LatencyView() {
+ super(ID);
+ }
+
+ // ------------------------------------------------------------------------
+ // ViewPart
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void createPartControl(@Nullable Composite parent) {
+ SashForm sf = new SashForm(parent, SWT.NONE);
+ TableViewer tableViewer = new TableViewer(sf, SWT.FULL_SELECTION | SWT.VIRTUAL);
+ fTableViewer = new LatencyTableViewer(tableViewer);
+ setInitialData();
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void setFocus() {
+ if (fTableViewer != null) {
+ fTableViewer.getTableViewer().getControl().setFocus();
+ }
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ if (fTableViewer != null) {
+ fTableViewer.dispose();
+ }
+ }
+
+ /**
+ * Set initial data into the viewer
+ */
+ private void setInitialData() {
+ if (fTableViewer != null) {
+ fTableViewer.setData(fTableViewer.getAnalysisModule());
+ }
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * France Lapointe Nguyen - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * @author France Lapointe Nguyen
+ */
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.messages"; //$NON-NLS-1$
+
+ /**
+ * Name of the duration column
+ */
+ public static @Nullable String LatencyTableViewer_duration;
+
+ /**
+ * Name of the end time column
+ */
+ public static @Nullable String LatencyTableViewer_endTime;
+
+ /**
+ * Name of the start time column
+ */
+ public static @Nullable String LatencyTableViewer_startTime;
+
+ /**
+ * Title of the scatter graph
+ */
+ public static @Nullable String LatencyView_title;
+
+ /**
+ * Title of the x axis of the scatter graph
+ */
+ public static @Nullable String LatencyView_xAxis;
+
+ /**
+ * Title of the y axis of the scatter graph
+ */
+ public static @Nullable String LatencyView_yAxis;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
--- /dev/null
+LatencyTableViewer_duration=Duration
+LatencyTableViewer_endTime=End Time
+LatencyTableViewer_startTime=Start Time
+LatencyView_title=Latency vs Time
+LatencyView_xAxis=Time
+LatencyView_yAxis=Latency
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;