From 49ffadb7f29f3637e06c52e3162576989f4632d2 Mon Sep 17 00:00:00 2001 From: Patrick Tasse Date: Tue, 22 May 2012 10:05:38 -0400 Subject: [PATCH] Bug 378402: Implementation of ControlFlow view and Resources view for LTTng 2.0. --- .../internal/lttng2/kernel/ui/Messages.java | 19 +- .../lttng2/kernel/ui/messages.properties | 18 +- .../kernel/ui/views/common/EventIterator.java | 122 +++++ .../views/controlflow/ControlFlowEntry.java | 95 ++-- .../views/controlflow/ControlFlowEvent.java | 30 ++ .../ui/views/controlflow/ControlFlowView.java | 385 ++++++++++++--- .../ui/views/resources/ResourcesEntry.java | 63 ++- .../ui/views/resources/ResourcesEvent.java | 41 ++ .../ui/views/resources/ResourcesView.java | 457 +++++++++++++++--- .../lttng2/ui/views/control/ControlView.java | 6 +- 10 files changed, 1059 insertions(+), 177 deletions(-) create mode 100644 org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/common/EventIterator.java create mode 100644 org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowEvent.java create mode 100644 org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesEvent.java diff --git a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/Messages.java b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/Messages.java index 485fd95334..2ca135f4d6 100644 --- a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/Messages.java +++ b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/Messages.java @@ -5,16 +5,25 @@ import org.eclipse.osgi.util.NLS; public class Messages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.linuxtools.internal.lttng2.kernel.ui.messages"; //$NON-NLS-1$ - public static String ControlFlowView_birthNsecColumn; - public static String ControlFlowView_birthSecColumn; - public static String ControlFlowView_brandColumn; - public static String ControlFlowView_cpuColumn; + public static String ControlFlowView_birthTimeColumn; public static String ControlFlowView_tidColumn; public static String ControlFlowView_ppidColumn; public static String ControlFlowView_processColumn; - public static String ControlFlowView_tgidColumn; public static String ControlFlowView_traceColumn; + + public static String ControlFlowView_stateTypeName; + public static String ControlFlowView_nextProcessActionNameText; + public static String ControlFlowView_nextProcessActionToolTipText; + public static String ControlFlowView_previousProcessActionNameText; + public static String ControlFlowView_previousProcessActionToolTipText; + public static String ResourcesView_stateTypeName; + public static String ResourcesView_nextResourceActionNameText; + public static String ResourcesView_nextResourceActionToolTipText; + public static String ResourcesView_previousResourceActionNameText; + public static String ResourcesView_previousResourceActionToolTipText; + + static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, Messages.class); diff --git a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/messages.properties b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/messages.properties index e843cdd217..ba3e361d09 100644 --- a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/messages.properties +++ b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/messages.properties @@ -1,9 +1,17 @@ -ControlFlowView_birthNsecColumn=Birth nsec -ControlFlowView_birthSecColumn=Birth sec -ControlFlowView_brandColumn=Brand -ControlFlowView_cpuColumn=CPU +ControlFlowView_birthTimeColumn=Birth time ControlFlowView_tidColumn=TID ControlFlowView_ppidColumn=PPID ControlFlowView_processColumn=Process -ControlFlowView_tgidColumn=TGID ControlFlowView_traceColumn=Trace + +ControlFlowView_stateTypeName=Process States +ControlFlowView_nextProcessActionNameText=Next Process +ControlFlowView_nextProcessActionToolTipText=Select Next Process +ControlFlowView_previousProcessActionNameText=Previous Process +ControlFlowView_previousProcessActionToolTipText=Select Previous Process + +ResourcesView_stateTypeName=Resource States +ResourcesView_nextResourceActionNameText=Next Resource +ResourcesView_nextResourceActionToolTipText=Select Next Resource +ResourcesView_previousResourceActionNameText=Previous Resource +ResourcesView_previousResourceActionToolTipText=Select Previous Resource diff --git a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/common/EventIterator.java b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/common/EventIterator.java new file mode 100644 index 0000000000..18a8a9e78d --- /dev/null +++ b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/common/EventIterator.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2012 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: + * Patrick Tasse - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.common; + +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent; + +public class EventIterator implements Iterator { + + private long fStartTime; + private long fEndTime; + private List fEventList; + private List fZoomedEventList; + private long fZoomedStartTime; + private long fZoomedEndTime; + private int fIndex = 0; + private int fZoomedIndex= 0; + private ITimeEvent fNext = null; + private ITimeEvent fZoomedNext = null; + + public EventIterator(List eventList, List zoomedEventList) { + this(eventList, zoomedEventList, Long.MIN_VALUE, Long.MAX_VALUE); + } + + public EventIterator(List eventList, List zoomedEventList, long startTime, long endTime) { + fEventList = eventList; + fZoomedEventList = zoomedEventList; + if (zoomedEventList != null && zoomedEventList.size() > 0) { + fZoomedStartTime = zoomedEventList.get(0).getTime(); + ITimeEvent lastEvent = zoomedEventList.get(zoomedEventList.size() - 1); + fZoomedEndTime = lastEvent.getTime() + lastEvent.getDuration(); + } else { + fZoomedStartTime = Long.MAX_VALUE; + fZoomedEndTime = Long.MIN_VALUE; + } + fStartTime = startTime; + fEndTime = endTime; + } + + @Override + public boolean hasNext() { + if (fNext == null && fEventList != null) { + while (fIndex < fEventList.size()) { + ITimeEvent event = fEventList.get(fIndex++); + if (event.getTime() + event.getDuration() >= fStartTime && event.getTime() <= fEndTime) { + fNext = event; + break; + } + } + if (fNext == null) { + fEventList = null; + } + } + + if (fZoomedNext == null && fZoomedEventList != null) { + while (fZoomedIndex < fZoomedEventList.size()) { + ITimeEvent event = fZoomedEventList.get(fZoomedIndex++); + if (event.getTime() + event.getDuration() >= fStartTime && event.getTime() <= fEndTime) { + fZoomedNext = event; + break; + } + } + if (fZoomedNext == null) { + fZoomedEventList = null; + } + } + + return fNext != null || fZoomedNext != null; + } + + @Override + public ITimeEvent next() { + if (hasNext()) { + if (fZoomedNext != null && (fNext == null || fZoomedNext.getTime() <= fNext.getTime())) { + if (fNext != null && fNext.getTime() == fZoomedNext.getTime()) { + long duration = fNext.getTime() + fNext.getDuration() - fZoomedEndTime; + if (duration > 0) { + fNext = new TimeEvent(fNext.getEntry(), fZoomedEndTime, duration); + } else { + fNext = null; + } + } + ITimeEvent event = fZoomedNext; + fZoomedNext = null; + return event; + } + if (fNext.getTime() < fZoomedEndTime && fNext.getTime() + fNext.getDuration() > fZoomedStartTime) { + ITimeEvent event = new TimeEvent(fNext.getEntry(), fNext.getTime(), fZoomedStartTime - fNext.getTime()); + long duration = fNext.getTime() + fNext.getDuration() - fZoomedEndTime; + if (duration > 0) { + fNext = new TimeEvent(fNext.getEntry(), fZoomedEndTime, duration); + } else { + fNext = null; + } + return event; + } + ITimeEvent event = fNext; + fNext = null; + return event; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowEntry.java b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowEntry.java index 12da4aedf0..1597439619 100644 --- a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowEntry.java +++ b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowEntry.java @@ -12,47 +12,53 @@ package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.controlflow; +import java.util.ArrayList; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; +import org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.common.EventIterator; import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; public class ControlFlowEntry implements ITimeGraphEntry, Comparable { + private int fThreadQuark; private CtfKernelTrace fTrace; - private ITimeGraphEntry parent = null; - private ITimeGraphEntry[] children = null; + private ControlFlowEntry fParent = null; + private ArrayList fChildren = new ArrayList(); private String fName; private int fThreadId; private int fPpid; + private long fBirthTime = -1; private long fStartTime = -1; private long fEndTime = -1; - List list = new LinkedList(); + private List fEventList = new ArrayList(); + private List fZoomedEventList = null; - public ControlFlowEntry(CtfKernelTrace trace, String execName, int threadId, int ppid, long startTime, long endTime) { + public ControlFlowEntry(int threadQuark, CtfKernelTrace trace, String execName, int threadId, int ppid, long birthTime, long startTime, long endTime) { + fThreadQuark = threadQuark; fTrace = trace; fName = execName; fThreadId = threadId; fPpid = ppid; + fBirthTime = birthTime; fStartTime = startTime; fEndTime = endTime; } @Override public ITimeGraphEntry getParent() { - return parent; + return fParent; } @Override public boolean hasChildren() { - return children != null && children.length > 0; + return fChildren != null && fChildren.size() > 0; } @Override - public ITimeGraphEntry[] getChildren() { - return children; + public ControlFlowEntry[] getChildren() { + return fChildren.toArray(new ControlFlowEntry[0]); } @Override @@ -60,43 +66,24 @@ public class ControlFlowEntry implements ITimeGraphEntry, Comparable getTimeEventsIterator() { - return list.iterator(); + return new EventIterator(fEventList, fZoomedEventList); } @Override public Iterator getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) { - return getTimeEventsIterator(); - } - - public void addTraceEvent(ITimeEvent event) { - long time = event.getTime(); - list.add(event); - if (fStartTime == -1 || time < fStartTime) { - fStartTime = time; - } - if (fEndTime == -1 || time > fEndTime) { - fEndTime = time; - } + return new EventIterator(fEventList, fZoomedEventList, startTime, stopTime); } @Override @@ -108,4 +95,50 @@ public class ControlFlowEntry implements ITimeGraphEntry, Comparable fEndTime) { + fEndTime = end; + } + } + } + + public void setEventList(List eventList) { + fEventList = eventList; + } + + public void setZoomedEventList(List eventList) { + fZoomedEventList = eventList; + } + + public void addChild(ControlFlowEntry child) { + child.fParent = this; + fChildren.add(child); + } } diff --git a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowEvent.java b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowEvent.java new file mode 100644 index 0000000000..f342b46f56 --- /dev/null +++ b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowEvent.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012 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: + * Patrick Tasse - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.controlflow; + +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent; + +public class ControlFlowEvent extends TimeEvent { + + private int fStatus; + + public ControlFlowEvent(ITimeGraphEntry entry, long time, long duration, int status) { + super(entry, time, duration); + fStatus = status; + } + + public int getStatus() { + return fStatus; + } +} diff --git a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowView.java b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowView.java index b759a96921..accaa50971 100644 --- a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowView.java +++ b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowView.java @@ -18,6 +18,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.ITreeContentProvider; @@ -25,13 +28,18 @@ import org.eclipse.jface.viewers.Viewer; import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Messages; import org.eclipse.linuxtools.lttng2.kernel.core.trace.Attributes; import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace; +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTimestamp; import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; +import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp; import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException; import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException; import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException; import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval; import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal; +import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal; import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal; import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemQuerier; import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment; @@ -39,18 +47,25 @@ import org.eclipse.linuxtools.tmf.ui.views.TmfView; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTimeListener; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.StateItem; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphCombo; -import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphProvider; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphSelectionEvent; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.Resolution; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.ui.IActionBars; public class ControlFlowView extends TmfView { @@ -63,23 +78,17 @@ public class ControlFlowView extends TmfView { */ public static final String ID = "org.eclipse.linuxtools.lttng2.kernel.ui.views.controlflow"; //$NON-NLS-1$ - private final String PROCESS_COLUMN = Messages.ControlFlowView_processColumn; - private final String TID_COLUMN = Messages.ControlFlowView_tidColumn; - private final String TGID_COLUMN = Messages.ControlFlowView_tgidColumn; - private final String PPID_COLUMN = Messages.ControlFlowView_ppidColumn; - private final String CPU_COLUMN = Messages.ControlFlowView_cpuColumn; - private final String BIRTH_SEC_COLUMN = Messages.ControlFlowView_birthSecColumn; - private final String BIRTH_NSEC_COLUMN = Messages.ControlFlowView_birthNsecColumn; - private final String TRACE_COLUMN = Messages.ControlFlowView_traceColumn; + private static final String PROCESS_COLUMN = Messages.ControlFlowView_processColumn; + private static final String TID_COLUMN = Messages.ControlFlowView_tidColumn; + private static final String PPID_COLUMN = Messages.ControlFlowView_ppidColumn; + private static final String BIRTH_TIME_COLUMN = Messages.ControlFlowView_birthTimeColumn; + private static final String TRACE_COLUMN = Messages.ControlFlowView_traceColumn; private final String[] COLUMN_NAMES = new String[] { PROCESS_COLUMN, TID_COLUMN, - TGID_COLUMN, PPID_COLUMN, - CPU_COLUMN, - BIRTH_SEC_COLUMN, - BIRTH_NSEC_COLUMN, + BIRTH_TIME_COLUMN, TRACE_COLUMN }; @@ -94,7 +103,7 @@ public class ControlFlowView extends TmfView { private TmfExperiment fSelectedExperiment; // The timegraph entry list - private ArrayList fEntryList; + private ArrayList fEntryList; // The start time private long fStartTime; @@ -102,6 +111,18 @@ public class ControlFlowView extends TmfView { // The end time private long fEndTime; + // The display width + private int fDisplayWidth; + + // The zoom thread + private ZoomThread fZoomThread; + + // The next resource action + private Action fNextResourceAction; + + // The previous resource action + private Action fPreviousResourceAction; + // ------------------------------------------------------------------------ // Classes // ------------------------------------------------------------------------ @@ -172,22 +193,70 @@ public class ControlFlowView extends TmfView { return entry.getName(); } else if (columnIndex == 1) { return Integer.toString(entry.getThreadId()); - } else if (columnIndex == 3) { - if (entry.getPPID() != -1) { + } else if (columnIndex == 2) { + if (entry.getPPID() > 0) { return Integer.toString(entry.getPPID()); } + } else if (columnIndex == 3) { + return Utils.formatTime(entry.getBirthTime(), TimeFormat.ABSOLUTE, Resolution.NANOSEC); + } else if (columnIndex == 4) { + return entry.getTrace().getName(); } return ""; //$NON-NLS-1$ } } + private class ZoomThread extends Thread { + private long fStartTime; + private long fEndTime; + private long fResolution; + private boolean fCancelled = false; + + public ZoomThread(long startTime, long endTime) { + super("ControlFlowView zoom"); //$NON-NLS-1$ + fStartTime = startTime; + fEndTime = endTime; + fResolution = Math.max(1, (fEndTime - fStartTime) / fDisplayWidth); + } + + @Override + public void run() { + if (fEntryList == null) { + return; + } + for (ControlFlowEntry entry : fEntryList) { + if (fCancelled) { + return; + } + zoom(entry); + } + redraw(); + } + + private void zoom(ControlFlowEntry entry) { + List zoomedEventList = getEventList(entry, fStartTime, fEndTime, fResolution); + entry.setZoomedEventList(zoomedEventList); + for (ControlFlowEntry child : entry.getChildren()) { + if (fCancelled) { + return; + } + zoom(child); + } + } + + public void cancel() { + fCancelled = true; + } + } + // ------------------------------------------------------------------------ // Constructors // ------------------------------------------------------------------------ public ControlFlowView() { super(ID); + fDisplayWidth = Display.getDefault().getBounds().width; } // ------------------------------------------------------------------------ @@ -205,30 +274,66 @@ public class ControlFlowView extends TmfView { fTimeGraphCombo.setTreeLabelProvider(new TreeLabelProvider()); - fTimeGraphCombo.setTimeGraphProvider(new TimeGraphProvider() { - @Override - public String getTraceClassName(ITimeGraphEntry trace) { - return "trace class"; //$NON-NLS-1$ + fTimeGraphCombo.setTimeGraphProvider(new TimeGraphPresentationProvider() { + private static final String UNKNOWN = "UNKNOWN"; //$NON-NLS-1$ + private static final String WAIT = "WAIT"; //$NON-NLS-1$ + private static final String USERMODE = "USERMODE"; //$NON-NLS-1$ + private static final String SYSCALL = "SYSCALL"; //$NON-NLS-1$ + private static final String INTERRUPTED = "INTERRUPTED"; //$NON-NLS-1$ + + @Override + public String getStateTypeName() { + return Messages.ControlFlowView_stateTypeName; } @Override - public String getStateName(StateColor color) { - return "state name"; //$NON-NLS-1$ + public StateItem[] getStateTable() { + return new StateItem[] { + new StateItem(new RGB(100, 100, 100), UNKNOWN), + new StateItem(new RGB(150, 150, 0), WAIT), + new StateItem(new RGB(0, 200, 0), USERMODE), + new StateItem(new RGB(0, 0, 200), SYSCALL), + new StateItem(new RGB(200, 100, 100), INTERRUPTED) + }; } - + @Override - public String getEventName(ITimeEvent event, boolean upper, boolean extInfo) { - return "event name"; //$NON-NLS-1$ + public int getEventTableIndex(ITimeEvent event) { + if (event instanceof ControlFlowEvent) { + int status = ((ControlFlowEvent) event).getStatus(); + if (status == Attributes.STATUS_WAIT) { + return 1; + } else if (status == Attributes.STATUS_RUN_USERMODE) { + return 2; + } else if (status == Attributes.STATUS_RUN_SYSCALL) { + return 3; + } else if (status == Attributes.STATUS_INTERRUPTED) { + return 4; + } + } + return 0; } - + @Override - public Map getEventHoverToolTipInfo(ITimeEvent event) { - return new HashMap(); + public String getEventName(ITimeEvent event) { + if (event instanceof ControlFlowEvent) { + int status = ((ControlFlowEvent) event).getStatus(); + if (status == Attributes.STATUS_WAIT) { + return WAIT; + } else if (status == Attributes.STATUS_RUN_USERMODE) { + return USERMODE; + } else if (status == Attributes.STATUS_RUN_SYSCALL) { + return SYSCALL; + } else if (status == Attributes.STATUS_INTERRUPTED) { + return INTERRUPTED; + } + } + return UNKNOWN; } @Override - public StateColor getEventColor(ITimeEvent event) { - return StateColor.BLACK; + public Map getEventHoverToolTipInfo(ITimeEvent event) { + return new HashMap(); } }); @@ -237,9 +342,16 @@ public class ControlFlowView extends TmfView { fTimeGraphCombo.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() { @Override public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) { - long startTime = event.getStartTime(); - long endTime = event.getEndTime(); - System.out.println("timeRangeUpdated: startTime="+startTime+" endTime="+endTime); + final long startTime = event.getStartTime(); + final long endTime = event.getEndTime(); + TmfTimeRange range = new TmfTimeRange(new CtfTmfTimestamp(startTime), new CtfTmfTimestamp(endTime)); + TmfTimestamp time = new CtfTmfTimestamp(fTimeGraphCombo.getTimeGraphViewer().getSelectedTime()); + broadcast(new TmfRangeSynchSignal(ControlFlowView.this, range, time)); + if (fZoomThread != null) { + fZoomThread.cancel(); + } + fZoomThread = new ZoomThread(startTime, endTime); + fZoomThread.start(); } }); @@ -247,19 +359,20 @@ public class ControlFlowView extends TmfView { @Override public void timeSelected(TimeGraphTimeEvent event) { long time = event.getTime(); - System.out.println("timeSelected: time="+time); + broadcast(new TmfTimeSynchSignal(ControlFlowView.this, new CtfTmfTimestamp(time))); } }); fTimeGraphCombo.addSelectionListener(new ITimeGraphSelectionListener() { @Override public void selectionChanged(TimeGraphSelectionEvent event) { - ITimeGraphEntry selection = event.getSelection(); - System.out.println("selectionChanged: source="+event.getSource()+" selection="+ (selection == null ? selection : selection.getName())); + //ITimeGraphEntry selection = event.getSelection(); } }); - final Thread thread = new Thread() { + fTimeGraphCombo.getTimeGraphViewer().setTimeCalendarFormat(true); + + final Thread thread = new Thread("ControlFlowView build") { //$NON-NLS-1$ @Override public void run() { if (TmfExperiment.getCurrentExperiment() != null) { @@ -268,6 +381,10 @@ public class ControlFlowView extends TmfView { } }; thread.start(); + + // View Action Handling + makeActions(); + contributeToActionBars(); } /* (non-Javadoc) @@ -288,26 +405,65 @@ public class ControlFlowView extends TmfView { return; } - final Thread thread = new Thread() { + final Thread thread = new Thread("ControlFlowView build") { //$NON-NLS-1$ @Override public void run() { selectExperiment(signal.getExperiment()); }}; - thread.run(); + thread.start(); + } + + @TmfSignalHandler + public void synchToTime(final TmfTimeSynchSignal signal) { + if (signal.getSource() == this) { + return; + } + final long time = signal.getCurrentTime().normalize(0, -9).getValue(); + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + if (fTimeGraphCombo.isDisposed()) { + return; + } + fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(time, true, signal.getSource()); + } + }); + } + + @TmfSignalHandler + public void synchToRange(final TmfRangeSynchSignal signal) { + if (signal.getSource() == this) { + return; + } + final long startTime = signal.getCurrentRange().getStartTime().normalize(0, -9).getValue(); + final long endTime = signal.getCurrentRange().getEndTime().normalize(0, -9).getValue(); + final long time = signal.getCurrentTime().normalize(0, -9).getValue(); + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + if (fTimeGraphCombo.isDisposed()) { + return; + } + fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime); + fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(time, false, signal.getSource()); + } + }); } + // ------------------------------------------------------------------------ + // Internal + // ------------------------------------------------------------------------ + @SuppressWarnings("unchecked") private void selectExperiment(TmfExperiment experiment) { fStartTime = Long.MAX_VALUE; fEndTime = Long.MIN_VALUE; fSelectedExperiment = (TmfExperiment) experiment; - HashMap traces = new HashMap(); - fEntryList = new ArrayList(); + fEntryList = new ArrayList(); for (ITmfTrace trace : experiment.getTraces()) { if (trace instanceof CtfKernelTrace) { CtfKernelTrace ctfKernelTrace = (CtfKernelTrace) trace; IStateSystemQuerier ssq = ctfKernelTrace.getStateSystem(); - ControlFlowEntry swapperEntry = null; long start = ssq.getStartTime(); long end = ssq.getCurrentEndTime(); fStartTime = Math.min(fStartTime, start); @@ -321,6 +477,9 @@ public class ControlFlowView extends TmfView { } catch (NumberFormatException e1) { continue; } + if (threadId == 0) { // ignore the swapper thread + continue; + } int execNameQuark = -1; try { try { @@ -330,28 +489,25 @@ public class ControlFlowView extends TmfView { } int ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID); List execNameIntervals = ssq.queryHistoryRange(execNameQuark, start, end); + long birthTime = -1; for (ITmfStateInterval execNameInterval : execNameIntervals) { if (!execNameInterval.getStateValue().isNull() && execNameInterval.getStateValue().getType() == 1) { String execName = execNameInterval.getStateValue().unboxStr(); long startTime = execNameInterval.getStartTime(); - long endTime = execNameInterval.getEndTime(); + long endTime = execNameInterval.getEndTime() + 1; + if (birthTime == -1) { + birthTime = startTime; + } int ppid = -1; if (ppidQuark != -1) { ITmfStateInterval ppidInterval = ssq.querySingleState(startTime, ppidQuark); ppid = ppidInterval.getStateValue().unboxInt(); } - ControlFlowEntry entry; - if (threadId == 0) { - if (swapperEntry == null) { - swapperEntry = new ControlFlowEntry(ctfKernelTrace, "swapper", threadId, ppid, startTime, endTime); - fEntryList.add(swapperEntry); - } - entry = swapperEntry; - } else { - entry = new ControlFlowEntry(ctfKernelTrace, execName, threadId, ppid, startTime, endTime); - fEntryList.add(entry); - } - entry.addTraceEvent(new TimeEvent(entry, startTime, endTime - startTime)); + ControlFlowEntry entry = new ControlFlowEntry(threadQuark, ctfKernelTrace, execName, threadId, ppid, birthTime, startTime, endTime); + fEntryList.add(entry); + entry.addEvent(new TimeEvent(entry, startTime, endTime - startTime)); + } else { + birthTime = -1; } } } catch (AttributeNotFoundException e) { @@ -363,8 +519,85 @@ public class ControlFlowView extends TmfView { } } } + buildTree(); refresh(); + ControlFlowEntry[] entries = fEntryList.toArray(new ControlFlowEntry[0]); + Arrays.sort(entries); + for (ControlFlowEntry entry : entries) { + buildStatusEvents(entry); + } + } + } + + private void buildTree() { + ArrayList rootList = new ArrayList(); + for (ControlFlowEntry entry : fEntryList) { + boolean root = true; + if (entry.getPPID() > 0) { + for (ControlFlowEntry parent : fEntryList) { + if (parent.getThreadId() == entry.getPPID() && + entry.getStartTime() >= parent.getStartTime() && + entry.getStartTime() <= parent.getEndTime()) { + parent.addChild(entry); + root = false; + break; + } + } + } + if (root) { + rootList.add(entry); + } } + fEntryList = rootList; + } + + private void buildStatusEvents(ControlFlowEntry entry) { + IStateSystemQuerier ssq = entry.getTrace().getStateSystem(); + long start = ssq.getStartTime(); + long end = ssq.getCurrentEndTime(); + long resolution = Math.max(1, (end - start) / fDisplayWidth); + List eventList = getEventList(entry, entry.getStartTime(), entry.getEndTime(), resolution); + entry.setEventList(eventList); + redraw(); + for (ITimeGraphEntry child : entry.getChildren()) { + buildStatusEvents((ControlFlowEntry) child); + } + } + + private List getEventList(ControlFlowEntry entry, long startTime, long endTime, long resolution) { + startTime = Math.max(startTime, entry.getStartTime()); + endTime = Math.min(endTime, entry.getEndTime()); + if (endTime <= startTime) { + return null; + } + IStateSystemQuerier ssq = entry.getTrace().getStateSystem(); + List eventList = null; + try { + int statusQuark = ssq.getQuarkRelative(entry.getThreadQuark(), Attributes.STATUS); + List statusIntervals = ssq.queryHistoryRange(statusQuark, startTime, endTime - 1, resolution); + eventList = new ArrayList(statusIntervals.size()); + long lastEndTime = -1; + for (ITmfStateInterval statusInterval : statusIntervals) { + long time = statusInterval.getStartTime(); + long duration = statusInterval.getEndTime() - time + 1; + int status = -1; + try { + status = statusInterval.getStateValue().unboxInt(); + } catch (StateValueTypeException e) { + e.printStackTrace(); + } + if (lastEndTime != time && lastEndTime != -1) { + eventList.add(new ControlFlowEvent(entry, lastEndTime, time - lastEndTime, 0)); + } + eventList.add(new ControlFlowEvent(entry, time, duration, status)); + lastEndTime = time + duration; + } + } catch (AttributeNotFoundException e) { + e.printStackTrace(); + } catch (TimeRangeException e) { + e.printStackTrace(); + } + return eventList; } private void refresh() { @@ -379,8 +612,50 @@ public class ControlFlowView extends TmfView { fTimeGraphCombo.setInput(entries); fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime); fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(fStartTime, fEndTime); + for (TreeColumn column : fTimeGraphCombo.getTreeViewer().getTree().getColumns()) { + column.pack(); + } + } + }); + } + + private void redraw() { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + if (fTimeGraphCombo.isDisposed()) { + return; + } + fTimeGraphCombo.redraw(); + fTimeGraphCombo.update(); } }); } + private void makeActions() { + fPreviousResourceAction = fTimeGraphCombo.getTimeGraphViewer().getPreviousItemAction(); + fPreviousResourceAction.setText(Messages.ControlFlowView_previousProcessActionNameText); + fPreviousResourceAction.setToolTipText(Messages.ControlFlowView_previousProcessActionToolTipText); + fNextResourceAction = fTimeGraphCombo.getTimeGraphViewer().getNextItemAction(); + fNextResourceAction.setText(Messages.ControlFlowView_nextProcessActionNameText); + fNextResourceAction.setToolTipText(Messages.ControlFlowView_nextProcessActionToolTipText); + } + + private void contributeToActionBars() { + IActionBars bars = getViewSite().getActionBars(); + fillLocalToolBar(bars.getToolBarManager()); + } + + private void fillLocalToolBar(IToolBarManager manager) { + manager.add(fTimeGraphCombo.getTimeGraphViewer().getShowLegendAction()); + manager.add(new Separator()); + manager.add(fTimeGraphCombo.getTimeGraphViewer().getResetScaleAction()); + manager.add(fTimeGraphCombo.getTimeGraphViewer().getPreviousEventAction()); + manager.add(fTimeGraphCombo.getTimeGraphViewer().getNextEventAction()); + manager.add(fPreviousResourceAction); + manager.add(fNextResourceAction); + manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomInAction()); + manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomOutAction()); + manager.add(new Separator()); + } } diff --git a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesEntry.java b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesEntry.java index 39b17a0383..6a67d2e3dd 100644 --- a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesEntry.java +++ b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesEntry.java @@ -12,27 +12,36 @@ package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources; +import java.util.ArrayList; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; +import org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.common.EventIterator; import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; public class ResourcesEntry implements ITimeGraphEntry { + public static enum Type { NULL, CPU, IRQ, SOFT_IRQ }; + + private int fQuark; private CtfKernelTrace fTrace; private ITimeGraphEntry fParent = null; private ITimeGraphEntry[] children = null; private String fName; + private Type fType; + private int fId; private long fStartTime; private long fEndTime; - List list = new LinkedList(); + private List fEventList = new ArrayList(); + private List fZoomedEventList = null; - public ResourcesEntry(ITimeGraphEntry parent, CtfKernelTrace trace, String cpuName) { - fParent = parent; + public ResourcesEntry(int quark, CtfKernelTrace trace, Type type, int id) { + fQuark = quark; fTrace = trace; - fName = cpuName; + fType = type; + fId = id; + fName = type.toString() + ' ' + Integer.toString(id); } @Override @@ -61,28 +70,50 @@ public class ResourcesEntry implements ITimeGraphEntry { } @Override - public long getStopTime() { + public long getEndTime() { return fEndTime; } @Override public Iterator getTimeEventsIterator() { - return list.iterator(); + return new EventIterator(fEventList, fZoomedEventList); } @Override public Iterator getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) { - return getTimeEventsIterator(); + return new EventIterator(fEventList, fZoomedEventList, startTime, stopTime); } - public void addTraceEvent(ITimeEvent event) { - long time = event.getTime(); - list.add(event); - if (fStartTime == -1 || time < fStartTime) { - fStartTime = time; - } - if (fEndTime == -1 || time > fEndTime) { - fEndTime = time; + public void setParent(ITimeGraphEntry parent) { + fParent = parent; + } + + public int getQuark() { + return fQuark; + } + + public CtfKernelTrace getTrace() { + return fTrace; + } + + public Type getType() { + return fType; + } + + public int getId() { + return fId; + } + + public void setEventList(List eventList) { + fEventList = eventList; + if (eventList != null && eventList.size() > 0) { + fStartTime = eventList.get(0).getTime(); + ITimeEvent lastEvent = eventList.get(eventList.size() - 1); + fEndTime = lastEvent.getTime() + lastEvent.getDuration(); } } + + public void setZoomedEventList(List eventList) { + fZoomedEventList = eventList; + } } diff --git a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesEvent.java b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesEvent.java new file mode 100644 index 0000000000..a7e65678ad --- /dev/null +++ b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesEvent.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2012 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: + * Patrick Tasse - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources; + +import org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources.ResourcesEntry.Type; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent; + +public class ResourcesEvent extends TimeEvent { + + private Type fType; + private int fValue; + + public ResourcesEvent(ResourcesEntry entry, long time, long duration, int value) { + super(entry, time, duration); + fType = entry.getType(); + fValue = value; + } + + public ResourcesEvent(ResourcesEntry entry, long time, long duration) { + super(entry, time, duration); + fType = Type.NULL; + } + + public int getValue() { + return fValue; + } + + public Type getType() { + return fType; + } +} diff --git a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesView.java b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesView.java index 0f60fbea33..a7786b96a4 100644 --- a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesView.java +++ b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesView.java @@ -13,33 +13,51 @@ package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Messages; +import org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources.ResourcesEntry.Type; import org.eclipse.linuxtools.lttng2.kernel.core.trace.Attributes; import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace; +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTimestamp; import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; import org.eclipse.linuxtools.tmf.core.event.TmfEvent; +import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp; import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException; import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException; import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException; import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval; import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal; +import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal; import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal; import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemQuerier; import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment; import org.eclipse.linuxtools.tmf.ui.views.TmfView; -import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphProvider; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTimeListener; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.StateItem; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphViewer; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent; import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IActionBars; public class ResourcesView extends TmfView { @@ -63,7 +81,7 @@ public class ResourcesView extends TmfView { private TmfExperiment fSelectedExperiment; // The time graph entry list - private ArrayList fEntryList; + private ArrayList fEntryList; // The start time private long fStartTime; @@ -73,25 +91,35 @@ public class ResourcesView extends TmfView { // The display width private int fDisplayWidth; + + // The next resource action + private Action fNextResourceAction; + + // The previous resource action + private Action fPreviousResourceAction; + + + // The zoom thread + private ZoomThread fZoomThread; // ------------------------------------------------------------------------ // Classes // ------------------------------------------------------------------------ - private class GroupEntry implements ITimeGraphEntry { - public ITimeGraphEntry fParent; - public ArrayList fChildren; + private class TraceEntry implements ITimeGraphEntry { + private CtfKernelTrace fTrace; + public ArrayList fChildren; public String fName; - public GroupEntry(ITimeGraphEntry parent, String name) { - fParent = parent; - fChildren = new ArrayList(); + public TraceEntry(CtfKernelTrace trace, String name) { + fTrace = trace; + fChildren = new ArrayList(); fName = name; } @Override public ITimeGraphEntry getParent() { - return fParent; + return null; } @Override @@ -100,8 +128,8 @@ public class ResourcesView extends TmfView { } @Override - public ITimeGraphEntry[] getChildren() { - return fChildren.toArray(new ITimeGraphEntry[0]); + public ResourcesEntry[] getChildren() { + return fChildren.toArray(new ResourcesEntry[0]); } @Override @@ -115,7 +143,7 @@ public class ResourcesView extends TmfView { } @Override - public long getStopTime() { + public long getEndTime() { return -1; } @@ -129,8 +157,59 @@ public class ResourcesView extends TmfView { return null; } - public void addChild(ITimeGraphEntry entry) { - fChildren.add(entry); + public CtfKernelTrace getTrace() { + return fTrace; + } + + public void addChild(ResourcesEntry entry) { + int index; + for (index = 0; index < fChildren.size(); index++) { + ResourcesEntry other = fChildren.get(index); + if (entry.getType().compareTo(other.getType()) < 0) { + break; + } else if (entry.getType().equals(other.getType())) { + if (entry.getId() < other.getId()) { + break; + } + } + } + entry.setParent(this); + fChildren.add(index, entry); + } + } + + private class ZoomThread extends Thread { + private long fStartTime; + private long fEndTime; + private boolean fCancelled = false; + + public ZoomThread(long startTime, long endTime) { + super("ResourcesView zoom"); //$NON-NLS-1$ + fStartTime = startTime; + fEndTime = endTime; + } + + @Override + public void run() { + if (fEntryList == null) { + return; + } + long resolution = Math.max(1, (fEndTime - fStartTime) / fDisplayWidth); + for (TraceEntry traceEntry : fEntryList) { + for (ITimeGraphEntry child : traceEntry.getChildren()) { + ResourcesEntry entry = (ResourcesEntry) child; + if (fCancelled) { + break; + } + List zoomedEventList = getEventList(entry, fStartTime, fEndTime, resolution, true); + entry.setZoomedEventList(zoomedEventList); + redraw(); + } + } + } + + public void cancel() { + fCancelled = true; } } @@ -154,20 +233,41 @@ public class ResourcesView extends TmfView { public void createPartControl(Composite parent) { fTimeGraphViewer = new TimeGraphViewer(parent, SWT.NONE); - fTimeGraphViewer.setTimeGraphProvider(new TimeGraphProvider() { - @Override - public String getTraceClassName(ITimeGraphEntry trace) { - return "trace class"; //$NON-NLS-1$ - } - - @Override - public String getStateName(StateColor color) { - return "state name"; //$NON-NLS-1$ + fTimeGraphViewer.setTimeGraphProvider(new TimeGraphPresentationProvider() { + private static final String UNKNOWN = "UNKNOWN"; //$NON-NLS-1$ + private static final String IDLE = "IDLE"; //$NON-NLS-1$ + private static final String BUSY = "BUSY"; //$NON-NLS-1$ + private static final String INTERRUPTED = "INTERRUPTED"; //$NON-NLS-1$ + private static final String RAISED = "RAISED"; //$NON-NLS-1$ + private static final String ACTIVE = "ACTIVE"; //$NON-NLS-1$ + + @Override + public String getStateTypeName() { + return Messages.ResourcesView_stateTypeName; } @Override - public String getEventName(ITimeEvent event, boolean upper, boolean extInfo) { - return "event name"; //$NON-NLS-1$ + public String getEventName(ITimeEvent event) { + if (event instanceof ResourcesEvent) { + ResourcesEvent resourcesEvent = (ResourcesEvent) event; + if (resourcesEvent.getType() == Type.CPU) { + int currentThread = resourcesEvent.getValue(); + if (currentThread == 0) { + return IDLE; + } else { + return BUSY; + } + } else if (resourcesEvent.getType() == Type.IRQ || resourcesEvent.getType() == Type.SOFT_IRQ) { + int cpu = resourcesEvent.getValue(); + if (cpu == Attributes.SOFT_IRQ_RAISED) { + return RAISED; + } + return ACTIVE; + } else { + return null; + } + } + return UNKNOWN; } @Override @@ -176,16 +276,69 @@ public class ResourcesView extends TmfView { } @Override - public StateColor getEventColor(ITimeEvent event) { - if (event.getTime() % 2 == 0) { - return StateColor.BLACK; - } else { - return StateColor.GRAY; + public StateItem[] getStateTable() { + return new StateItem[] { + new StateItem(new RGB(100, 100, 100), UNKNOWN), + new StateItem(new RGB(200, 200, 200), IDLE), + new StateItem(new RGB(0, 200, 0), BUSY), + new StateItem(new RGB(200, 100, 100), INTERRUPTED), + new StateItem(new RGB(200, 200, 0), RAISED), + new StateItem(new RGB(200, 100, 100), ACTIVE) + }; + } + + @Override + public int getEventTableIndex(ITimeEvent event) { + if (event instanceof ResourcesEvent) { + ResourcesEvent resourcesEvent = (ResourcesEvent) event; + if (resourcesEvent.getType() == Type.CPU) { + int currentThread = resourcesEvent.getValue(); + if (currentThread == 0) { + return 1; // IDLE + } else { + return 2; // BUSY + } + } else if (resourcesEvent.getType() == Type.IRQ || resourcesEvent.getType() == Type.SOFT_IRQ) { + int cpu = resourcesEvent.getValue(); + if (cpu == Attributes.SOFT_IRQ_RAISED) { + return 4; // RAISED + } + return 5; // ACTIVE + } else { + return -1; // NULL + } + } + return 0; // UNKNOWN + } + }); + + fTimeGraphViewer.setTimeCalendarFormat(true); + + fTimeGraphViewer.addRangeListener(new ITimeGraphRangeListener() { + @Override + public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) { + long startTime = event.getStartTime(); + long endTime = event.getEndTime(); + TmfTimeRange range = new TmfTimeRange(new CtfTmfTimestamp(startTime), new CtfTmfTimestamp(endTime)); + TmfTimestamp time = new CtfTmfTimestamp(fTimeGraphViewer.getSelectedTime()); + broadcast(new TmfRangeSynchSignal(ResourcesView.this, range, time)); + if (fZoomThread != null) { + fZoomThread.cancel(); } + fZoomThread = new ZoomThread(startTime, endTime); + fZoomThread.start(); } }); - final Thread thread = new Thread() { + fTimeGraphViewer.addTimeListener(new ITimeGraphTimeListener() { + @Override + public void timeSelected(TimeGraphTimeEvent event) { + long time = event.getTime(); + broadcast(new TmfTimeSynchSignal(ResourcesView.this, new CtfTmfTimestamp(time))); + } + }); + + final Thread thread = new Thread("ResourcesView build") { //$NON-NLS-1$ @Override public void run() { if (TmfExperiment.getCurrentExperiment() != null) { @@ -194,6 +347,10 @@ public class ResourcesView extends TmfView { } }; thread.start(); + + // View Action Handling + makeActions(); + contributeToActionBars(); } /* (non-Javadoc) @@ -214,7 +371,7 @@ public class ResourcesView extends TmfView { return; } - final Thread thread = new Thread() { + final Thread thread = new Thread("ResourcesView build") { //$NON-NLS-1$ @Override public void run() { selectExperiment(signal.getExperiment()); @@ -222,51 +379,183 @@ public class ResourcesView extends TmfView { thread.start(); } + @TmfSignalHandler + public void synchToTime(final TmfTimeSynchSignal signal) { + if (signal.getSource() == this) { + return; + } + final long time = signal.getCurrentTime().normalize(0, -9).getValue(); + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + if (fTimeGraphViewer.getControl().isDisposed()) { + return; + } + fTimeGraphViewer.setSelectedTime(time, true, signal.getSource()); + } + }); + } + + @TmfSignalHandler + public void synchToRange(final TmfRangeSynchSignal signal) { + if (signal.getSource() == this) { + return; + } + final long startTime = signal.getCurrentRange().getStartTime().normalize(0, -9).getValue(); + final long endTime = signal.getCurrentRange().getEndTime().normalize(0, -9).getValue(); + final long time = signal.getCurrentTime().normalize(0, -9).getValue(); + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + if (fTimeGraphViewer.getControl().isDisposed()) { + return; + } + fTimeGraphViewer.setStartFinishTime(startTime, endTime); + fTimeGraphViewer.setSelectedTime(time, false, signal.getSource()); + } + }); + } + + // ------------------------------------------------------------------------ + // Internal + // ------------------------------------------------------------------------ + @SuppressWarnings("unchecked") private void selectExperiment(TmfExperiment experiment) { fStartTime = Long.MAX_VALUE; fEndTime = Long.MIN_VALUE; fSelectedExperiment = (TmfExperiment) experiment; - fEntryList = new ArrayList(); + fEntryList = new ArrayList(); for (ITmfTrace trace : experiment.getTraces()) { - GroupEntry groupEntry = new GroupEntry(null, trace.getPath()); - fEntryList.add(groupEntry); - refresh(); if (trace instanceof CtfKernelTrace) { CtfKernelTrace ctfKernelTrace = (CtfKernelTrace) trace; + TraceEntry groupEntry = new TraceEntry(ctfKernelTrace, trace.getName()); + fEntryList.add(groupEntry); IStateSystemQuerier ssq = ctfKernelTrace.getStateSystem(); - long start = ssq.getStartTime(); - long end = ssq.getCurrentEndTime(); - fStartTime = Math.min(fStartTime, start); - fEndTime = Math.max(fEndTime, end); + long startTime = ssq.getStartTime(); + long endTime = ssq.getCurrentEndTime() + 1; + fStartTime = Math.min(fStartTime, startTime); + fEndTime = Math.max(fEndTime, endTime); List cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$ - for (int cpuQuark : cpuQuarks) { - String cpuName = "CPU " + ssq.getAttributeName(cpuQuark); - ResourcesEntry entry = new ResourcesEntry(groupEntry, ctfKernelTrace, cpuName); - try { - int currentThreadQuark = ssq.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD); - long resolution = (end - start) / fDisplayWidth; - List currentThreadIntervals = ssq.queryHistoryRange(currentThreadQuark, start, end, resolution); - for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) { - if (!currentThreadInterval.getStateValue().isNull() && currentThreadInterval.getStateValue().getType() == 0) { - int currentThread = currentThreadInterval.getStateValue().unboxInt(); - long startTime = currentThreadInterval.getStartTime(); - long endTime = currentThreadInterval.getEndTime(); - entry.addTraceEvent(new TimeEvent(entry, startTime, endTime - startTime)); - } + ResourcesEntry[] cpuEntries = new ResourcesEntry[cpuQuarks.size()]; + for (int i = 0; i < cpuQuarks.size(); i++) { + int cpuQuark = cpuQuarks.get(i); + int cpu = Integer.parseInt(ssq.getAttributeName(cpuQuark)); + ResourcesEntry entry = new ResourcesEntry(cpuQuark, ctfKernelTrace, Type.CPU, cpu); + groupEntry.addChild(entry); + cpuEntries[i] = entry; + } + List irqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.IRQS, "*"); //$NON-NLS-1$ + ResourcesEntry[] irqEntries = new ResourcesEntry[irqQuarks.size()]; + for (int i = 0; i < irqQuarks.size(); i++) { + int irqQuark = irqQuarks.get(i); + int irq = Integer.parseInt(ssq.getAttributeName(irqQuark)); + ResourcesEntry entry = new ResourcesEntry(irqQuark, ctfKernelTrace, Type.IRQ, irq); + groupEntry.addChild(entry); + irqEntries[i] = entry; + } + List softIrqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$ + ResourcesEntry[] softIrqEntries = new ResourcesEntry[softIrqQuarks.size()]; + for (int i = 0; i < softIrqQuarks.size(); i++) { + int softIrqQuark = softIrqQuarks.get(i); + int softIrq = Integer.parseInt(ssq.getAttributeName(softIrqQuark)); + ResourcesEntry entry = new ResourcesEntry(softIrqQuark, ctfKernelTrace, Type.SOFT_IRQ, softIrq); + groupEntry.addChild(entry); + softIrqEntries[i] = entry; + } + } + } + refresh(); + for (TraceEntry traceEntry : fEntryList) { + CtfKernelTrace ctfKernelTrace = ((TraceEntry) traceEntry).getTrace(); + IStateSystemQuerier ssq = ctfKernelTrace.getStateSystem(); + long startTime = ssq.getStartTime(); + long endTime = ssq.getCurrentEndTime() + 1; + long resolution = (endTime - startTime) / fDisplayWidth; + for (ResourcesEntry entry : traceEntry.getChildren()) { + List eventList = getEventList(entry, startTime, endTime, resolution, false); + entry.setEventList(eventList); + redraw(); + } + } + } + + private List getEventList(ResourcesEntry entry, long startTime, long endTime, long resolution, boolean includeNull) { + IStateSystemQuerier ssq = entry.getTrace().getStateSystem(); + List eventList = null; + int quark = entry.getQuark(); + try { + if (entry.getType().equals(Type.CPU)) { + int currentThreadQuark = ssq.getQuarkRelative(quark, Attributes.CURRENT_THREAD); + List currentThreadIntervals = ssq.queryHistoryRange(currentThreadQuark, startTime, endTime - 1, resolution); + eventList = new ArrayList(currentThreadIntervals.size()); + long lastEndTime = -1; + for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) { + if (!currentThreadInterval.getStateValue().isNull()) { + int currentThread = currentThreadInterval.getStateValue().unboxInt(); + long time = currentThreadInterval.getStartTime(); + long duration = currentThreadInterval.getEndTime() - time + 1; + if (lastEndTime != time && lastEndTime != -1) { + eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime)); } - } catch (AttributeNotFoundException e) { - e.printStackTrace(); - } catch (TimeRangeException e) { - e.printStackTrace(); - } catch (StateValueTypeException e) { - e.printStackTrace(); + eventList.add(new ResourcesEvent(entry, time, duration, currentThread)); + lastEndTime = time + duration; } - groupEntry.addChild(entry); - refresh(); + } + } else if (entry.getType().equals(Type.IRQ)) { + List irqIntervals = ssq.queryHistoryRange(quark, startTime, endTime - 1, resolution); + eventList = new ArrayList(irqIntervals.size()); + long lastEndTime = -1; + boolean lastIsNull = true; + for (ITmfStateInterval irqInterval : irqIntervals) { + long time = irqInterval.getStartTime(); + long duration = irqInterval.getEndTime() - time + 1; + if (!irqInterval.getStateValue().isNull()) { + int cpu = irqInterval.getStateValue().unboxInt(); + eventList.add(new ResourcesEvent(entry, time, duration, cpu)); + lastIsNull = false; + } else { + if (lastEndTime != time && lastEndTime != -1 && lastIsNull) { + eventList.add(new ResourcesEvent(entry, lastEndTime, time - lastEndTime, -1)); + } + if (includeNull) { + eventList.add(new ResourcesEvent(entry, time, duration)); + } + lastIsNull = true; + } + lastEndTime = time + duration; + } + } else if (entry.getType().equals(Type.SOFT_IRQ)) { + List softIrqIntervals = ssq.queryHistoryRange(quark, startTime, endTime - 1, resolution); + eventList = new ArrayList(softIrqIntervals.size()); + long lastEndTime = -1; + boolean lastIsNull = true; + for (ITmfStateInterval softIrqInterval : softIrqIntervals) { + long time = softIrqInterval.getStartTime(); + long duration = softIrqInterval.getEndTime() - time + 1; + if (!softIrqInterval.getStateValue().isNull()) { + int cpu = softIrqInterval.getStateValue().unboxInt(); + eventList.add(new ResourcesEvent(entry, time, duration, cpu)); + } else { + if (lastEndTime != time && lastEndTime != -1 && lastIsNull) { + eventList.add(new ResourcesEvent(entry, lastEndTime, time - lastEndTime, -1)); + } + if (includeNull) { + eventList.add(new ResourcesEvent(entry, time, duration)); + } + lastIsNull = true; + } + lastEndTime = time + duration; } } + } catch (AttributeNotFoundException e) { + e.printStackTrace(); + } catch (TimeRangeException e) { + e.printStackTrace(); + } catch (StateValueTypeException e) { + e.printStackTrace(); } + return eventList; } private void refresh() { @@ -276,11 +565,53 @@ public class ResourcesView extends TmfView { if (fTimeGraphViewer.getControl().isDisposed()) { return; } - fTimeGraphViewer.setInput(fEntryList.toArray(new ITimeGraphEntry[0])); + ITimeGraphEntry[] entries = fEntryList.toArray(new ITimeGraphEntry[0]); + Arrays.sort(entries); + fTimeGraphViewer.setInput(entries); fTimeGraphViewer.setTimeBounds(fStartTime, fEndTime); fTimeGraphViewer.setStartFinishTime(fStartTime, fEndTime); } }); } + + private void redraw() { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + if (fTimeGraphViewer.getControl().isDisposed()) { + return; + } + fTimeGraphViewer.getControl().redraw(); + fTimeGraphViewer.getControl().update(); + } + }); + } + + private void makeActions() { + fPreviousResourceAction = fTimeGraphViewer.getPreviousItemAction(); + fPreviousResourceAction.setText(Messages.ResourcesView_previousResourceActionNameText); + fPreviousResourceAction.setToolTipText(Messages.ResourcesView_previousResourceActionToolTipText); + fNextResourceAction = fTimeGraphViewer.getNextItemAction(); + fNextResourceAction.setText(Messages.ResourcesView_nextResourceActionNameText); + fNextResourceAction.setToolTipText(Messages.ResourcesView_previousResourceActionToolTipText); + } + + private void contributeToActionBars() { + IActionBars bars = getViewSite().getActionBars(); + fillLocalToolBar(bars.getToolBarManager()); + } + + private void fillLocalToolBar(IToolBarManager manager) { + manager.add(fTimeGraphViewer.getShowLegendAction()); + manager.add(new Separator()); + manager.add(fTimeGraphViewer.getResetScaleAction()); + manager.add(fTimeGraphViewer.getPreviousEventAction()); + manager.add(fTimeGraphViewer.getNextEventAction()); + manager.add(fPreviousResourceAction); + manager.add(fNextResourceAction); + manager.add(fTimeGraphViewer.getZoomInAction()); + manager.add(fTimeGraphViewer.getZoomOutAction()); + manager.add(new Separator()); + } } diff --git a/org.eclipse.linuxtools.lttng2.ui/src/org/eclipse/linuxtools/internal/lttng2/ui/views/control/ControlView.java b/org.eclipse.linuxtools.lttng2.ui/src/org/eclipse/linuxtools/internal/lttng2/ui/views/control/ControlView.java index b9ad132c15..23883cb86f 100644 --- a/org.eclipse.linuxtools.lttng2.ui/src/org/eclipse/linuxtools/internal/lttng2/ui/views/control/ControlView.java +++ b/org.eclipse.linuxtools.lttng2.ui/src/org/eclipse/linuxtools/internal/lttng2/ui/views/control/ControlView.java @@ -71,9 +71,11 @@ public class ControlView extends ViewPart implements ITraceControlComponentChang // ------------------------------------------------------------------------ // Accessors // ------------------------------------------------------------------------ - + /** - * @return returns the trace control tree node (model). + * Returns the trace control tree node (model) + * + * @return the trace control tree node (model). */ public ITraceControlComponent getTraceControlRoot() { return fRoot; -- 2.34.1