From 1cf2531114f2ff545e67a9450dfa7243fb5dacdd Mon Sep 17 00:00:00 2001 From: Patrick Tasse Date: Mon, 27 Jan 2014 17:20:13 -0500 Subject: [PATCH] lttng: Support live updating of Control Flow view and Resources view - Update AbstractTimeGraphView to use a list as input element and to support a time graph content provider. - Update AbstractTimeGraphView to create one separate BuildThread per trace in the trace set. Change buildEventList method to be called independently for each trace in the trace set. - Update AbstractTimeGraphView to use a CopyOnWriteArrayList for the entry list of each trace, and stop exposing the entry list map to subclasses. Add interface to add or remove a list of entries to/from the entry list of a trace. - Update AbstractTimeGraphView refresh method to refresh the time graph combo or time graph viewer when possible and avoid calling setInput, which resets all tree elements. - Update AbstractTimeGraphView to perform packing of tree columns only once. - Add support in TimeGraphEntry to update the end time and to replace the last event with an event starting at the same time. - Fix TmfEventsEditor sending TmfTraceClosed with null trace. - Update ControlFlowView and ResourcesView to build the event list for a trace continuously in a loop until its state system build is complete. Support continuous updating of the entry list and its tree structure, and partial updating of the event list at each iteration. - Update state system history range query to allow punctual time range. Change-Id: I440c369ddef703f8fbceac221cfea0c0699348c0 Signed-off-by: Patrick Tasse Reviewed-on: https://git.eclipse.org/r/21161 Tested-by: Hudson CI Reviewed-by: Alexandre Montplaisir Reviewed-by: Matthew Khouzam IP-Clean: Matthew Khouzam Tested-by: Matthew Khouzam --- .../views/controlflow/ControlFlowEntry.java | 14 +- .../ControlFlowPresentationProvider.java | 6 + .../ui/views/controlflow/ControlFlowView.java | 396 +++++++++--------- .../ui/views/resources/ResourcesEntry.java | 16 +- .../ResourcesPresentationProvider.java | 6 + .../ui/views/resources/ResourcesView.java | 181 ++++---- .../tmf/core/statesystem/StateSystem.java | 2 +- .../tmf/ui/editors/TmfEventsEditor.java | 6 +- .../timegraph/AbstractTimeGraphView.java | 171 ++++++-- .../timegraph/model/TimeGraphEntry.java | 29 +- 10 files changed, 495 insertions(+), 332 deletions(-) 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 cd591ce5a0..598deee1c1 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2013 Ericsson, École Polytechnique de Montréal + * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -13,7 +13,7 @@ package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.controlflow; -import org.eclipse.linuxtools.lttng2.kernel.core.trace.LttngKernelTrace; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeGraphEntry; /** @@ -21,7 +21,7 @@ import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeGraphEntry; */ public class ControlFlowEntry extends TimeGraphEntry { - private final LttngKernelTrace fTrace; + private final ITmfTrace fTrace; private final int fThreadId; private final int fParentThreadId; private final int fThreadQuark; @@ -44,7 +44,7 @@ public class ControlFlowEntry extends TimeGraphEntry { * @param endTime * The end time of this process */ - public ControlFlowEntry(int quark, LttngKernelTrace trace, String execName, int threadId, int parentThreadId, long startTime, long endTime) { + public ControlFlowEntry(int quark, ITmfTrace trace, String execName, int threadId, int parentThreadId, long startTime, long endTime) { super(execName, startTime, endTime); fTrace = trace; fThreadId = threadId; @@ -62,11 +62,11 @@ public class ControlFlowEntry extends TimeGraphEntry { } /** - * Get the entry's kernel trace + * Get the entry's trace * - * @return the entry's kernel trace + * @return the entry's trace */ - public LttngKernelTrace getTrace() { + public ITmfTrace getTrace() { return fTrace; } diff --git a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowPresentationProvider.java b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowPresentationProvider.java index cdb01ecb46..b8cc96a11f 100644 --- a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowPresentationProvider.java +++ b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/controlflow/ControlFlowPresentationProvider.java @@ -128,6 +128,9 @@ public class ControlFlowPresentationProvider extends TimeGraphPresentationProvid } ControlFlowEntry entry = (ControlFlowEntry) event.getEntry(); LttngKernelAnalysisModule module = entry.getTrace().getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); + if (module == null) { + return retMap; + } ITmfStateSystem ssq = module.getStateSystem(); if (ssq == null) { return retMap; @@ -186,6 +189,9 @@ public class ControlFlowPresentationProvider extends TimeGraphPresentationProvid } ControlFlowEntry entry = (ControlFlowEntry) event.getEntry(); LttngKernelAnalysisModule module = entry.getTrace().getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); + if (module == null) { + return; + } ITmfStateSystem ss = module.getStateSystem(); if (ss == null) { return; 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 2ac5ec527e..75487c63ab 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2013 Ericsson, École Polytechnique de Montréal + * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -14,19 +14,18 @@ package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.controlflow; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes; import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Activator; import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Messages; -import org.eclipse.linuxtools.lttng2.kernel.core.trace.LttngKernelTrace; import org.eclipse.linuxtools.lttng2.kernel.ui.analysis.LttngKernelAnalysisModule; import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException; import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException; @@ -82,6 +81,9 @@ public class ControlFlowView extends AbstractTimeGraphView { TID_COLUMN }; + // Timeout between updates in the build thread in ms + private static final long BUILD_UPDATE_TIMEOUT = 500; + // ------------------------------------------------------------------------ // Constructors // ------------------------------------------------------------------------ @@ -217,161 +219,169 @@ public class ControlFlowView extends AbstractTimeGraphView { // ------------------------------------------------------------------------ @Override - protected void buildEventList(final ITmfTrace trace, IProgressMonitor monitor) { - setStartTime(Long.MAX_VALUE); - setEndTime(Long.MIN_VALUE); + protected void buildEventList(final ITmfTrace trace, ITmfTrace parentTrace, IProgressMonitor monitor) { + LttngKernelAnalysisModule module = trace.getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); + if (module == null) { + return; + } + module.schedule(); + module.waitForInitialization(); + ITmfStateSystem ssq = module.getStateSystem(); + if (ssq == null) { + return; + } - ArrayList rootList = new ArrayList<>(); - for (ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) { + List entryList = new ArrayList<>(); + Map entryMap = new HashMap<>(); + + long start = ssq.getStartTime(); + setStartTime(Math.min(getStartTime(), start)); + + boolean complete = false; + while (!complete) { if (monitor.isCanceled()) { return; } - if (aTrace instanceof LttngKernelTrace) { - ArrayList entryList = new ArrayList<>(); - LttngKernelTrace ctfKernelTrace = (LttngKernelTrace) aTrace; - LttngKernelAnalysisModule module = ctfKernelTrace.getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); - module.schedule(); - if (!module.waitForCompletion(new NullProgressMonitor())) { - continue; + complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT); + if (ssq.isCancelled()) { + return; + } + long end = ssq.getCurrentEndTime(); + if (start == end && !complete) { // when complete execute one last time regardless of end time + continue; + } + setEndTime(Math.max(getEndTime(), end + 1)); + List threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$ + for (int threadQuark : threadQuarks) { + if (monitor.isCanceled()) { + return; } - ITmfStateSystem ssq = module.getStateSystem(); - if (ssq == null) { + String threadName = ssq.getAttributeName(threadQuark); + int threadId = -1; + try { + threadId = Integer.parseInt(threadName); + } catch (NumberFormatException e1) { continue; } - ssq.waitUntilBuilt(); - if (ssq.isCancelled()) { + if (threadId <= 0) { // ignore the 'unknown' (-1) and swapper (0) threads continue; } - long start = ssq.getStartTime(); - long end = ssq.getCurrentEndTime() + 1; - setStartTime(Math.min(getStartTime(), start)); - setEndTime(Math.max(getEndTime(), end)); - List threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$ - for (int threadQuark : threadQuarks) { - if (monitor.isCanceled()) { - return; - } - String threadName = ssq.getAttributeName(threadQuark); - int threadId = -1; - try { - threadId = Integer.parseInt(threadName); - } catch (NumberFormatException e1) { - continue; - } - if (threadId == 0) { // ignore the swapper thread - continue; - } - int execNameQuark = -1; - try { - try { - execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME); - } catch (AttributeNotFoundException e) { - continue; - } - int ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID); - List execNameIntervals = ssq.queryHistoryRange(execNameQuark, start, end - 1); - // use monitor when available in api + try { + int execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME); + List execNameIntervals = ssq.queryHistoryRange(execNameQuark, start, end); + for (ITmfStateInterval execNameInterval : execNameIntervals) { if (monitor.isCanceled()) { return; } - ControlFlowEntry entry = null; - for (ITmfStateInterval execNameInterval : execNameIntervals) { - if (monitor.isCanceled()) { - return; - } - if (!execNameInterval.getStateValue().isNull() && - execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) { - String execName = execNameInterval.getStateValue().unboxStr(); - long startTime = execNameInterval.getStartTime(); - long endTime = execNameInterval.getEndTime() + 1; + ControlFlowEntry entry = entryMap.get(threadId); + if (!execNameInterval.getStateValue().isNull() && + execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) { + String execName = execNameInterval.getStateValue().unboxStr(); + long startTime = execNameInterval.getStartTime(); + long endTime = execNameInterval.getEndTime() + 1; + if (entry == null) { int ppid = -1; - if (ppidQuark != -1) { - ITmfStateInterval ppidInterval = ssq.querySingleState(startTime, ppidQuark); + int ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID); + ITmfStateInterval ppidInterval = ssq.querySingleState(startTime, ppidQuark); + if (!ppidInterval.getStateValue().isNull()) { ppid = ppidInterval.getStateValue().unboxInt(); } - if (entry == null) { - entry = new ControlFlowEntry(threadQuark, ctfKernelTrace, execName, threadId, ppid, startTime, endTime); - entryList.add(entry); - } else { - // update the name of the entry to the - // latest execName - entry.setName(execName); - } - entry.addEvent(new TimeEvent(entry, startTime, endTime - startTime)); + entry = new ControlFlowEntry(threadQuark, trace, execName, threadId, ppid, startTime, endTime); + entryList.add(entry); + entryMap.put(threadId, entry); } else { - entry = null; + // update the name of the entry to the latest execName + entry.setName(execName); + entry.updateEndTime(endTime); } + } else { + entryMap.remove(threadId); } - } catch (AttributeNotFoundException e) { - e.printStackTrace(); - } catch (TimeRangeException e) { - e.printStackTrace(); - } catch (StateValueTypeException e) { - e.printStackTrace(); - } catch (StateSystemDisposedException e) { - /* Ignored */ } + } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) { + e.printStackTrace(); + } catch (StateSystemDisposedException e) { + /* Ignored */ } - buildTree(entryList, rootList); } - Collections.sort(rootList, getEntryComparator()); - putEntryList(trace, new ArrayList(rootList)); - if (trace.equals(getTrace())) { + updateTree(entryList, parentTrace); + + if (parentTrace.equals(getTrace())) { refresh(); } - } - for (ControlFlowEntry entry : rootList) { - if (monitor.isCanceled()) { - return; + + for (ControlFlowEntry entry : entryList) { + if (monitor.isCanceled()) { + return; + } + buildStatusEvents(entry.getTrace(), entry, monitor, start, end); } - buildStatusEvents(entry.getTrace(), entry, monitor); + + start = end; } } - private static void buildTree(ArrayList entryList, - ArrayList rootList) { + private void updateTree(List entryList, ITmfTrace parentTrace) { + List rootListToAdd = new ArrayList<>(); + List rootListToRemove = new ArrayList<>(); + List rootList = getEntryList(parentTrace); + for (ControlFlowEntry entry : entryList) { - boolean root = true; - if (entry.getParentThreadId() > 0) { + boolean root = (entry.getParent() == null); + if (root && entry.getParentThreadId() > 0) { for (ControlFlowEntry parent : entryList) { if (parent.getThreadId() == entry.getParentThreadId() && entry.getStartTime() >= parent.getStartTime() && entry.getStartTime() <= parent.getEndTime()) { parent.addChild(entry); root = false; + if (rootList != null && rootList.contains(entry)) { + rootListToRemove.add(entry); + } break; } } } - if (root) { - rootList.add(entry); + if (root && (rootList == null || !rootList.contains(entry))) { + rootListToAdd.add(entry); } } + + addToEntryList(parentTrace, rootListToAdd); + removeFromEntryList(parentTrace, rootListToRemove); } - private void buildStatusEvents(ITmfTrace trace, ControlFlowEntry entry, IProgressMonitor monitor) { - LttngKernelAnalysisModule module = entry.getTrace().getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); - ITmfStateSystem ssq = module.getStateSystem(); - if (ssq == null) { - return; - } - long start = ssq.getStartTime(); - long end = ssq.getCurrentEndTime() + 1; - long resolution = Math.max(1, (end - start) / getDisplayWidth()); - List eventList = getEventList(entry, entry.getStartTime(), entry.getEndTime(), resolution, monitor); - if (monitor.isCanceled()) { - return; - } - entry.setEventList(eventList); - if (trace.equals(getTrace())) { - redraw(); + private void buildStatusEvents(ITmfTrace trace, ControlFlowEntry entry, IProgressMonitor monitor, long start, long end) { + if (start < entry.getEndTime() && end > entry.getStartTime()) { + LttngKernelAnalysisModule module = entry.getTrace().getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); + if (module == null) { + return; + } + ITmfStateSystem ssq = module.getStateSystem(); + if (ssq == null) { + return; + } + + long startTime = Math.max(start, entry.getStartTime()); + long endTime = Math.min(end + 1, entry.getEndTime()); + long resolution = Math.max(1, (end - ssq.getStartTime()) / getDisplayWidth()); + List eventList = getEventList(entry, startTime, endTime, resolution, monitor); + if (monitor.isCanceled()) { + return; + } + for (ITimeEvent event : eventList) { + entry.addEvent(event); + } + if (trace.equals(getTrace())) { + redraw(); + } } for (ITimeGraphEntry child : entry.getChildren()) { if (monitor.isCanceled()) { return; } - buildStatusEvents(trace, (ControlFlowEntry) child, monitor); + buildStatusEvents(trace, (ControlFlowEntry) child, monitor, start, end); } } @@ -388,6 +398,9 @@ public class ControlFlowView extends AbstractTimeGraphView { return null; } LttngKernelAnalysisModule module = entry.getTrace().getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); + if (module == null) { + return null; + } ITmfStateSystem ssq = module.getStateSystem(); if (ssq == null) { return null; @@ -415,9 +428,7 @@ public class ControlFlowView extends AbstractTimeGraphView { eventList.add(new TimeEvent(entry, time, duration, status)); lastEndTime = time + duration; } - } catch (AttributeNotFoundException e) { - e.printStackTrace(); - } catch (TimeRangeException e) { + } catch (AttributeNotFoundException | TimeRangeException e) { e.printStackTrace(); } catch (StateSystemDisposedException e) { /* Ignored */ @@ -428,8 +439,8 @@ public class ControlFlowView extends AbstractTimeGraphView { /** * Returns a value corresponding to the selected entry. * - * Used in conjunction with selectEntry to change the selected entry. If one - * of these methods is overridden in child class, then both should be. + * Used in conjunction with synchingToTime to change the selected entry. If + * one of these methods is overridden in child class, then both should be. * * @param time * The currently selected time @@ -437,40 +448,40 @@ public class ControlFlowView extends AbstractTimeGraphView { */ private int getSelectionValue(long time) { int thread = -1; - for (ITmfTrace trace : fTraceManager.getActiveTraceSet()) { + ITmfTrace[] traces = TmfTraceManager.getTraceSet(getTrace()); + if (traces == null) { + return thread; + } + for (ITmfTrace trace : traces) { if (thread > 0) { break; } - if (trace instanceof LttngKernelTrace) { - LttngKernelTrace ctfKernelTrace = (LttngKernelTrace) trace; - LttngKernelAnalysisModule module = ctfKernelTrace.getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); - ITmfStateSystem ssq = module.getStateSystem(); - if (ssq == null) { - continue; - } - if (time >= ssq.getStartTime() && time <= ssq.getCurrentEndTime()) { - List currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$ - for (int currentThreadQuark : currentThreadQuarks) { - try { - ITmfStateInterval currentThreadInterval = ssq.querySingleState(time, currentThreadQuark); - int currentThread = currentThreadInterval.getStateValue().unboxInt(); - if (currentThread > 0) { - int statusQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThread), Attributes.STATUS); - ITmfStateInterval statusInterval = ssq.querySingleState(time, statusQuark); - if (statusInterval.getStartTime() == time) { - thread = currentThread; - break; - } + LttngKernelAnalysisModule module = trace.getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); + if (module == null) { + continue; + } + ITmfStateSystem ssq = module.getStateSystem(); + if (ssq == null) { + continue; + } + if (time >= ssq.getStartTime() && time <= ssq.getCurrentEndTime()) { + List currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$ + for (int currentThreadQuark : currentThreadQuarks) { + try { + ITmfStateInterval currentThreadInterval = ssq.querySingleState(time, currentThreadQuark); + int currentThread = currentThreadInterval.getStateValue().unboxInt(); + if (currentThread > 0) { + int statusQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThread), Attributes.STATUS); + ITmfStateInterval statusInterval = ssq.querySingleState(time, statusQuark); + if (statusInterval.getStartTime() == time) { + thread = currentThread; + break; } - } catch (AttributeNotFoundException e) { - e.printStackTrace(); - } catch (TimeRangeException e) { - e.printStackTrace(); - } catch (StateValueTypeException e) { - e.printStackTrace(); - } catch (StateSystemDisposedException e) { - /* Ignored */ } + } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) { + e.printStackTrace(); + } catch (StateSystemDisposedException e) { + /* Ignored */ } } } @@ -498,64 +509,61 @@ public class ControlFlowView extends AbstractTimeGraphView { protected List getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) { List list = new ArrayList<>(); ITmfTrace[] traces = TmfTraceManager.getTraceSet(getTrace()); - List entryList = getEntryListMap().get(getTrace()); + List entryList = getEntryList(getTrace()); if (traces == null || entryList == null) { return list; } for (ITmfTrace trace : traces) { - if (trace instanceof LttngKernelTrace) { - LttngKernelAnalysisModule module = trace.getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); - ITmfStateSystem ssq = module.getStateSystem(); - if (ssq == null) { + LttngKernelAnalysisModule module = trace.getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); + if (module == null) { + continue; + } + ITmfStateSystem ssq = module.getStateSystem(); + if (ssq == null) { + continue; + } + try { + long start = Math.max(startTime, ssq.getStartTime()); + long end = Math.min(endTime, ssq.getCurrentEndTime()); + if (end < start) { continue; } - try { - long start = Math.max(startTime, ssq.getStartTime()); - long end = Math.min(endTime, ssq.getCurrentEndTime()); - if (end < start) { - continue; - } - List currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$ - for (int currentThreadQuark : currentThreadQuarks) { - // adjust the query range to include the previous and following intervals - long qstart = Math.max(ssq.querySingleState(start, currentThreadQuark).getStartTime() - 1, ssq.getStartTime()); - long qend = Math.min(ssq.querySingleState(end, currentThreadQuark).getEndTime() + 1, ssq.getCurrentEndTime()); - List currentThreadIntervals = ssq.queryHistoryRange(currentThreadQuark, qstart, qend, resolution, monitor); - int prevThread = 0; - long prevEnd = 0; - long lastEnd = 0; - for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) { - if (monitor.isCanceled()) { - return null; - } - long time = currentThreadInterval.getStartTime(); - if (time != lastEnd) { - // don't create links where there are gaps in intervals due to the resolution - prevThread = 0; - prevEnd = 0; - } - int thread = currentThreadInterval.getStateValue().unboxInt(); - if (thread > 0 && prevThread > 0) { - ITimeGraphEntry prevEntry = findEntry(entryList, trace, prevThread); - ITimeGraphEntry nextEntry = findEntry(entryList, trace, thread); - list.add(new TimeLinkEvent(prevEntry, nextEntry, prevEnd, time - prevEnd, 0)); - } - lastEnd = currentThreadInterval.getEndTime() + 1; - if (thread != 0) { - prevThread = thread; - prevEnd = lastEnd; - } + List currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$ + for (int currentThreadQuark : currentThreadQuarks) { + // adjust the query range to include the previous and following intervals + long qstart = Math.max(ssq.querySingleState(start, currentThreadQuark).getStartTime() - 1, ssq.getStartTime()); + long qend = Math.min(ssq.querySingleState(end, currentThreadQuark).getEndTime() + 1, ssq.getCurrentEndTime()); + List currentThreadIntervals = ssq.queryHistoryRange(currentThreadQuark, qstart, qend, resolution, monitor); + int prevThread = 0; + long prevEnd = 0; + long lastEnd = 0; + for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) { + if (monitor.isCanceled()) { + return null; + } + long time = currentThreadInterval.getStartTime(); + if (time != lastEnd) { + // don't create links where there are gaps in intervals due to the resolution + prevThread = 0; + prevEnd = 0; + } + int thread = currentThreadInterval.getStateValue().unboxInt(); + if (thread > 0 && prevThread > 0) { + ITimeGraphEntry prevEntry = findEntry(entryList, trace, prevThread); + ITimeGraphEntry nextEntry = findEntry(entryList, trace, thread); + list.add(new TimeLinkEvent(prevEntry, nextEntry, prevEnd, time - prevEnd, 0)); + } + lastEnd = currentThreadInterval.getEndTime() + 1; + if (thread != 0) { + prevThread = thread; + prevEnd = lastEnd; } } - } catch (TimeRangeException e) { - e.printStackTrace(); - } catch (AttributeNotFoundException e) { - e.printStackTrace(); - } catch (StateValueTypeException e) { - e.printStackTrace(); - } catch (StateSystemDisposedException e) { - /* Ignored */ } + } catch (TimeRangeException | AttributeNotFoundException | StateValueTypeException e) { + e.printStackTrace(); + } catch (StateSystemDisposedException e) { + /* Ignored */ } } return list; 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 81da0d2bf7..07a3c93fbb 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 @@ -13,7 +13,7 @@ package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources; -import org.eclipse.linuxtools.lttng2.kernel.core.trace.LttngKernelTrace; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeGraphEntry; /** @@ -36,7 +36,7 @@ public class ResourcesEntry extends TimeGraphEntry { } private final int fId; - private final LttngKernelTrace fTrace; + private final ITmfTrace fTrace; private final Type fType; private final int fQuark; @@ -58,7 +58,7 @@ public class ResourcesEntry extends TimeGraphEntry { * @param id * The id of this entry */ - public ResourcesEntry(int quark, LttngKernelTrace trace, String name, long startTime, long endTime, Type type, int id) { + public ResourcesEntry(int quark, ITmfTrace trace, String name, long startTime, long endTime, Type type, int id) { super(name, startTime, endTime); fId = id; fTrace = trace; @@ -80,7 +80,7 @@ public class ResourcesEntry extends TimeGraphEntry { * @param id * The id of this entry */ - public ResourcesEntry(LttngKernelTrace trace, String name, long startTime, long endTime, int id) { + public ResourcesEntry(ITmfTrace trace, String name, long startTime, long endTime, int id) { this(-1, trace, name, startTime, endTime, Type.NULL, id); } @@ -100,7 +100,7 @@ public class ResourcesEntry extends TimeGraphEntry { * @param id * The id of this entry */ - public ResourcesEntry(int quark, LttngKernelTrace trace, long startTime, long endTime, Type type, int id) { + public ResourcesEntry(int quark, ITmfTrace trace, long startTime, long endTime, Type type, int id) { this(quark, trace, type.toString() + " " + id, startTime, endTime, type, id); //$NON-NLS-1$ } @@ -114,11 +114,11 @@ public class ResourcesEntry extends TimeGraphEntry { } /** - * Get the entry's kernel trace + * Get the entry's trace * - * @return the entry's kernel trace + * @return the entry's trace */ - public LttngKernelTrace getTrace() { + public ITmfTrace getTrace() { return fTrace; } diff --git a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesPresentationProvider.java b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesPresentationProvider.java index 162ba4a2cb..c607f30a5e 100644 --- a/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesPresentationProvider.java +++ b/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/resources/ResourcesPresentationProvider.java @@ -158,6 +158,9 @@ public class ResourcesPresentationProvider extends TimeGraphPresentationProvider if (tcEvent.hasValue()) { LttngKernelAnalysisModule module = entry.getTrace().getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); + if (module == null) { + return retMap; + } ITmfStateSystem ss = module.getStateSystem(); if (ss == null) { return retMap; @@ -288,6 +291,9 @@ public class ResourcesPresentationProvider extends TimeGraphPresentationProvider } LttngKernelAnalysisModule module = entry.getTrace().getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); + if (module == null) { + return; + } ITmfStateSystem ss = module.getStateSystem(); if (ss == null) { return; 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 7bf37217a8..b208853f6f 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2013 Ericsson, École Polytechnique de Montréal + * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -14,14 +14,15 @@ package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes; 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.LttngKernelTrace; import org.eclipse.linuxtools.lttng2.kernel.ui.analysis.LttngKernelAnalysisModule; import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException; import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException; @@ -30,7 +31,6 @@ import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException; import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval; import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem; import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; -import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager; import org.eclipse.linuxtools.tmf.ui.views.timegraph.AbstractTimeGraphView; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent; import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.NullTimeEvent; @@ -51,6 +51,9 @@ public class ResourcesView extends AbstractTimeGraphView { Messages.ResourcesView_stateTypeName }; + // Timeout between updates in the build thread in ms + private static final long BUILD_UPDATE_TIMEOUT = 500; + // ------------------------------------------------------------------------ // Constructors // ------------------------------------------------------------------------ @@ -63,6 +66,10 @@ public class ResourcesView extends AbstractTimeGraphView { setFilterColumns(FILTER_COLUMN_NAMES); } + // ------------------------------------------------------------------------ + // Internal + // ------------------------------------------------------------------------ + @Override protected String getNextText() { return Messages.ResourcesView_nextResourceActionNameText; @@ -83,93 +90,104 @@ public class ResourcesView extends AbstractTimeGraphView { return Messages.ResourcesView_previousResourceActionToolTipText; } - // ------------------------------------------------------------------------ - // Internal - // ------------------------------------------------------------------------ - @Override - protected void buildEventList(ITmfTrace trace, IProgressMonitor monitor) { - setStartTime(Long.MAX_VALUE); - setEndTime(Long.MIN_VALUE); + protected void buildEventList(ITmfTrace trace, ITmfTrace parentTrace, IProgressMonitor monitor) { + LttngKernelAnalysisModule module = trace.getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); + if (module == null) { + return; + } + module.schedule(); + module.waitForInitialization(); + ITmfStateSystem ssq = module.getStateSystem(); + if (ssq == null) { + return; + } - ArrayList entryList = new ArrayList<>(); - for (ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) { + Map entryMap = new HashMap<>(); + TimeGraphEntry traceEntry = null; + + long startTime = ssq.getStartTime(); + long start = startTime; + setStartTime(Math.min(getStartTime(), startTime)); + boolean complete = false; + while (!complete) { if (monitor.isCanceled()) { return; } - if (aTrace instanceof LttngKernelTrace) { - LttngKernelTrace lttngKernelTrace = (LttngKernelTrace) aTrace; - LttngKernelAnalysisModule module = lttngKernelTrace.getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); - module.schedule(); - if (!module.waitForCompletion(new NullProgressMonitor())) { - continue; - } - ITmfStateSystem ssq = module.getStateSystem(); - if (ssq == null) { - continue; - } - ssq.waitUntilBuilt(); - if (ssq.isCancelled()) { - continue; - } - long startTime = ssq.getStartTime(); - long endTime = ssq.getCurrentEndTime() + 1; - ResourcesEntry groupEntry = new ResourcesEntry(lttngKernelTrace, aTrace.getName(), startTime, endTime, 0); - entryList.add(groupEntry); - setStartTime(Math.min(getStartTime(), startTime)); - setEndTime(Math.max(getEndTime(), endTime)); - List cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$ - 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, lttngKernelTrace, getStartTime(), getEndTime(), Type.CPU, cpu); - groupEntry.addChild(entry); - cpuEntries[i] = entry; + complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT); + if (ssq.isCancelled()) { + return; + } + long end = ssq.getCurrentEndTime(); + if (start == end && !complete) { // when complete execute one last time regardless of end time + continue; + } + long endTime = end + 1; + setEndTime(Math.max(getEndTime(), endTime)); + + if (traceEntry == null) { + traceEntry = new ResourcesEntry(trace, trace.getName(), startTime, endTime, 0); + List entryList = Collections.singletonList(traceEntry); + addToEntryList(parentTrace, entryList); + } else { + traceEntry.updateEndTime(endTime); + } + + List cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$ + for (Integer cpuQuark : cpuQuarks) { + int cpu = Integer.parseInt(ssq.getAttributeName(cpuQuark)); + ResourcesEntry entry = entryMap.get(cpuQuark); + if (entry == null) { + entry = new ResourcesEntry(cpuQuark, trace, startTime, endTime, Type.CPU, cpu); + entryMap.put(cpuQuark, entry); + traceEntry.addChild(entry); + } else { + entry.updateEndTime(endTime); } - 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, lttngKernelTrace, getStartTime(), getEndTime(), Type.IRQ, irq); - groupEntry.addChild(entry); - irqEntries[i] = entry; + } + List irqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.IRQS, "*"); //$NON-NLS-1$ + for (Integer irqQuark : irqQuarks) { + int irq = Integer.parseInt(ssq.getAttributeName(irqQuark)); + ResourcesEntry entry = entryMap.get(irqQuark); + if (entry == null) { + entry = new ResourcesEntry(irqQuark, trace, startTime, endTime, Type.IRQ, irq); + entryMap.put(irqQuark, entry); + traceEntry.addChild(entry); + } else { + entry.updateEndTime(endTime); } - 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, lttngKernelTrace, getStartTime(), getEndTime(), Type.SOFT_IRQ, softIrq); - groupEntry.addChild(entry); - softIrqEntries[i] = entry; + } + List softIrqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$ + for (Integer softIrqQuark : softIrqQuarks) { + int softIrq = Integer.parseInt(ssq.getAttributeName(softIrqQuark)); + ResourcesEntry entry = entryMap.get(softIrqQuark); + if (entry == null) { + entry = new ResourcesEntry(softIrqQuark, trace, startTime, endTime, Type.SOFT_IRQ, softIrq); + entryMap.put(softIrqQuark, entry); + traceEntry.addChild(entry); + } else { + entry.updateEndTime(endTime); } } - } - putEntryList(trace, new ArrayList(entryList)); - if (trace.equals(getTrace())) { - refresh(); - } - for (ResourcesEntry traceEntry : entryList) { - if (monitor.isCanceled()) { - return; + if (parentTrace.equals(getTrace())) { + refresh(); } - LttngKernelTrace lttngKernelTrace = traceEntry.getTrace(); - LttngKernelAnalysisModule module = lttngKernelTrace.getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); - ITmfStateSystem ssq = module.getStateSystem(); - if (ssq == null) { - continue; - } - long startTime = ssq.getStartTime(); - long endTime = ssq.getCurrentEndTime() + 1; - long resolution = (endTime - startTime) / getDisplayWidth(); + long resolution = Math.max(1, (endTime - ssq.getStartTime()) / getDisplayWidth()); for (TimeGraphEntry entry : traceEntry.getChildren()) { - List eventList = getEventList(entry, startTime, endTime, resolution, monitor); - entry.setEventList(eventList); + if (monitor.isCanceled()) { + return; + } + List eventList = getEventList(entry, start, endTime, resolution, monitor); + if (eventList != null) { + for (ITimeEvent event : eventList) { + entry.addEvent(event); + } + } redraw(); } + + start = end; } } @@ -179,6 +197,9 @@ public class ResourcesView extends AbstractTimeGraphView { IProgressMonitor monitor) { ResourcesEntry resourcesEntry = (ResourcesEntry) entry; LttngKernelAnalysisModule module = resourcesEntry.getTrace().getAnalysisModules(LttngKernelAnalysisModule.class).get(LttngKernelAnalysisModule.ID); + if (module == null) { + return null; + } ITmfStateSystem ssq = module.getStateSystem(); if (ssq == null) { return null; @@ -282,11 +303,7 @@ public class ResourcesView extends AbstractTimeGraphView { } } - } catch (AttributeNotFoundException e) { - e.printStackTrace(); - } catch (TimeRangeException e) { - e.printStackTrace(); - } catch (StateValueTypeException e) { + } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) { e.printStackTrace(); } catch (StateSystemDisposedException e) { /* Ignored */ diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/StateSystem.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/StateSystem.java index 9420753d54..ecba187de8 100644 --- a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/StateSystem.java +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/StateSystem.java @@ -618,7 +618,7 @@ public class StateSystem implements ITmfStateSystemBuilder { long ts, tEnd; /* Make sure the time range makes sense */ - if (t2 <= t1) { + if (t2 < t1) { throw new TimeRangeException(); } diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/editors/TmfEventsEditor.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/editors/TmfEventsEditor.java index ce6bd2dd1d..6957e5bfba 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/editors/TmfEventsEditor.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/editors/TmfEventsEditor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2013 Ericsson + * Copyright (c) 2010, 2014 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -202,7 +202,9 @@ public class TmfEventsEditor extends TmfEditor implements ITmfTraceEditor, IReus @Override public void propertyChanged(final Object source, final int propId) { if (propId == IEditorPart.PROP_INPUT && getEditorInput() instanceof TmfEditorInput) { - broadcast(new TmfTraceClosedSignal(this, fTrace)); + if (fTrace != null) { + broadcast(new TmfTraceClosedSignal(this, fTrace)); + } fTraceSelected = false; fFile = ((TmfEditorInput) getEditorInput()).getFile(); fTrace = ((TmfEditorInput) getEditorInput()).getTrace(); diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/timegraph/AbstractTimeGraphView.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/timegraph/AbstractTimeGraphView.java index c690ed48bf..1c5dc2d5be 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/timegraph/AbstractTimeGraphView.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/timegraph/AbstractTimeGraphView.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2013 Ericsson, École Polytechnique de Montréal + * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -17,12 +17,12 @@ package org.eclipse.linuxtools.tmf.ui.views.timegraph; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; @@ -48,7 +48,9 @@ import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp; import org.eclipse.linuxtools.tmf.core.timestamp.TmfNanoTimestamp; import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange; import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager; import org.eclipse.linuxtools.tmf.ui.views.TmfView; +import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphContentProvider; 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; @@ -103,7 +105,7 @@ public abstract class AbstractTimeGraphView extends TmfView { /** The trace to entry list hash map */ private final Map> fEntryListMap = new HashMap<>(); - /* The trace to build thread hash map */ + /** The trace to build thread hash map */ private final Map fBuildThreadMap = new HashMap<>(); /** The start time */ @@ -127,7 +129,7 @@ public abstract class AbstractTimeGraphView extends TmfView { /** A comparator class */ private Comparator fEntryComparator = null; - /** The redraw state used to prevent unnecessary queuing of display runnables */ + /** The redraw state used to prevent unnecessary queuing of display runnables */ private State fRedrawState = State.IDLE; /** The redraw synchronization object */ @@ -148,6 +150,9 @@ public abstract class AbstractTimeGraphView extends TmfView { /** The filter column label array, or null if filter is not used */ private String[] fFilterColumns; + /** The pack done flag */ + private boolean fPackDone = false; + /** The filter label provider, or null if filter is not used */ private TreeLabelProvider fFilterLabelProvider; @@ -171,7 +176,9 @@ public abstract class AbstractTimeGraphView extends TmfView { void refresh(); - void setInput(ITimeGraphEntry[] entries); + void setInput(Object input); + + Object getInput(); void redraw(); @@ -217,10 +224,15 @@ public abstract class AbstractTimeGraphView extends TmfView { } @Override - public void setInput(ITimeGraphEntry[] input) { + public void setInput(Object input) { viewer.setInput(input); } + @Override + public Object getInput() { + return viewer.getInput(); + } + @Override public void refresh() { viewer.refresh(); @@ -275,10 +287,15 @@ public abstract class AbstractTimeGraphView extends TmfView { } @Override - public void setInput(ITimeGraphEntry[] input) { + public void setInput(Object input) { combo.setInput(input); } + @Override + public Object getInput() { + return combo.getInput(); + } + @Override public void refresh() { combo.refresh(); @@ -318,8 +335,14 @@ public abstract class AbstractTimeGraphView extends TmfView { } @Override - public Object[] getElements(Object inputElement) { - return (ITimeGraphEntry[]) inputElement; + public ITimeGraphEntry[] getElements(Object inputElement) { + if (inputElement != null) { + try { + return ((List) inputElement).toArray(new ITimeGraphEntry[0]); + } catch (ClassCastException e) { + } + } + return new ITimeGraphEntry[0]; } @Override @@ -343,6 +366,21 @@ public abstract class AbstractTimeGraphView extends TmfView { } + private class TimeGraphContentProvider implements ITimeGraphContentProvider { + + @Override + public ITimeGraphEntry[] getElements(Object inputElement) { + if (inputElement != null) { + try { + return ((List) inputElement).toArray(new ITimeGraphEntry[0]); + } catch (ClassCastException e) { + } + } + return new ITimeGraphEntry[0]; + } + + } + /** * Base class to provide the labels for the tree viewer. Views extending * this class typically need to override the getColumnText method if they @@ -385,19 +423,21 @@ public abstract class AbstractTimeGraphView extends TmfView { private class BuildThread extends Thread { private final ITmfTrace fBuildTrace; + private final ITmfTrace fParentTrace; private final IProgressMonitor fMonitor; - public BuildThread(final ITmfTrace trace, final String name) { + public BuildThread(final ITmfTrace trace, final ITmfTrace parentTrace, final String name) { super(name + " build"); //$NON-NLS-1$ fBuildTrace = trace; + fParentTrace = parentTrace; fMonitor = new NullProgressMonitor(); } @Override public void run() { - buildEventList(fBuildTrace, fMonitor); + buildEventList(fBuildTrace, fParentTrace, fMonitor); synchronized (fBuildThreadMap) { - fBuildThreadMap.remove(this); + fBuildThreadMap.remove(fBuildTrace); } } @@ -645,25 +685,69 @@ public abstract class AbstractTimeGraphView extends TmfView { } /** - * Gets the entry list map + * Gets the entry list for a trace + * + * @param trace + * the trace * * @return the entry list map + * @since 3.0 */ - protected Map> getEntryListMap() { - return Collections.unmodifiableMap(fEntryListMap); + protected List getEntryList(ITmfTrace trace) { + synchronized (fEntryListMap) { + return fEntryListMap.get(trace); + } } /** - * Adds an entry to the entry list + * Adds a trace entry list to the entry list map * * @param trace * the trace to add * @param list - * The list of time graph entries + * the list of time graph entries */ protected void putEntryList(ITmfTrace trace, List list) { - synchronized(fEntryListMap) { - fEntryListMap.put(trace, list); + synchronized (fEntryListMap) { + fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list)); + } + } + + /** + * Adds a list of entries to a trace's entry list + * + * @param trace + * the trace + * @param list + * the list of time graph entries to add + * @since 3.0 + */ + protected void addToEntryList(ITmfTrace trace, List list) { + synchronized (fEntryListMap) { + List entryList = fEntryListMap.get(trace); + if (entryList == null) { + fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list)); + } else { + entryList.addAll(list); + } + } + } + + /** + * Removes a list of entries from a trace's entry list + * + * @param trace + * the trace + * @param list + * the list of time graph entries to remove + * @since 3.0 + */ + protected void removeFromEntryList(ITmfTrace trace, List list) { + synchronized (fEntryListMap) { + List entryList = fEntryListMap.get(trace); + if (entryList != null) { + entryList.removeAll(list); + } } } @@ -711,6 +795,8 @@ public abstract class AbstractTimeGraphView extends TmfView { public void createPartControl(Composite parent) { if (fColumns == null || fLabelProvider == null) { fTimeGraphWrapper = new TimeGraphViewerWrapper(parent, SWT.NONE); + TimeGraphViewer viewer = fTimeGraphWrapper.getTimeGraphViewer(); + viewer.setTimeGraphContentProvider(new TimeGraphContentProvider()); } else { TimeGraphComboWrapper wrapper = new TimeGraphComboWrapper(parent, SWT.NONE); fTimeGraphWrapper = wrapper; @@ -721,6 +807,7 @@ public abstract class AbstractTimeGraphView extends TmfView { combo.setFilterContentProvider(new TreeContentProvider()); combo.setFilterLabelProvider(fFilterLabelProvider); combo.setFilterColumns(fFilterColumns); + combo.setTimeGraphContentProvider(new TimeGraphContentProvider()); } fTimeGraphWrapper.setTimeGraphProvider(fPresentation); @@ -820,9 +907,11 @@ public abstract class AbstractTimeGraphView extends TmfView { @TmfSignalHandler public void traceClosed(final TmfTraceClosedSignal signal) { synchronized (fBuildThreadMap) { - BuildThread buildThread = fBuildThreadMap.remove(signal.getTrace()); - if (buildThread != null) { - buildThread.cancel(); + for (ITmfTrace trace : TmfTraceManager.getTraceSet(signal.getTrace())) { + BuildThread buildThread = fBuildThreadMap.remove(trace); + if (buildThread != null) { + buildThread.cancel(); + } } } synchronized (fEntryListMap) { @@ -916,10 +1005,14 @@ public abstract class AbstractTimeGraphView extends TmfView { synchronized (fEntryListMap) { fEntryList = fEntryListMap.get(fTrace); if (fEntryList == null) { + setStartTime(Long.MAX_VALUE); + setEndTime(Long.MIN_VALUE); synchronized (fBuildThreadMap) { - BuildThread buildThread = new BuildThread(fTrace, getName()); - fBuildThreadMap.put(fTrace, buildThread); - buildThread.start(); + for (ITmfTrace trace : TmfTraceManager.getTraceSet(fTrace)) { + BuildThread buildThread = new BuildThread(trace, fTrace, getName()); + fBuildThreadMap.put(trace, buildThread); + buildThread.start(); + } } } else { fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); @@ -947,10 +1040,13 @@ public abstract class AbstractTimeGraphView extends TmfView { * * @param trace * The trace being built + * @param parentTrace + * The parent of the trace set, or the trace itself * @param monitor * The progress monitor object + * @since 3.0 */ - protected abstract void buildEventList(final ITmfTrace trace, IProgressMonitor monitor); + protected abstract void buildEventList(ITmfTrace trace, ITmfTrace parentTrace, IProgressMonitor monitor); /** * Gets the list of event for an entry in a given timerange @@ -1002,18 +1098,24 @@ public abstract class AbstractTimeGraphView extends TmfView { if (fTimeGraphWrapper.isDisposed()) { return; } - ITimeGraphEntry[] entries = null; + boolean hasEntries = false; synchronized (fEntryListMap) { fEntryList = fEntryListMap.get(fTrace); if (fEntryList == null) { - fEntryList = new ArrayList<>(); + fEntryList = new CopyOnWriteArrayList<>(); + } else if (fEntryComparator != null) { + List list = new ArrayList<>(fEntryList); + Collections.sort(list, fEntryComparator); + fEntryList.clear(); + fEntryList.addAll(list); } - entries = fEntryList.toArray(new ITimeGraphEntry[0]); + hasEntries = fEntryList.size() != 0; } - if (fEntryComparator != null) { - Arrays.sort(entries, fEntryComparator); + if (fEntryList != fTimeGraphWrapper.getInput()) { + fTimeGraphWrapper.setInput(fEntryList); + } else { + fTimeGraphWrapper.refresh(); } - fTimeGraphWrapper.setInput(entries); fTimeGraphWrapper.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime); long selectionBeginTime = fTrace == null ? 0 : fTraceManager.getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); @@ -1025,10 +1127,13 @@ public abstract class AbstractTimeGraphView extends TmfView { fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime); fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime); - if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) { + if (fTimeGraphWrapper instanceof TimeGraphComboWrapper && !fPackDone) { for (TreeColumn column : ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getTree().getColumns()) { column.pack(); } + if (hasEntries) { + fPackDone = true; + } } startZoomThread(startTime, endTime); diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/model/TimeGraphEntry.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/model/TimeGraphEntry.java index 995828634d..2b4b583ab9 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/model/TimeGraphEntry.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/model/TimeGraphEntry.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2013 Ericsson, École Polytechnique de Montréal + * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -16,6 +16,7 @@ package org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * An entry for use in the time graph views @@ -28,7 +29,7 @@ public class TimeGraphEntry implements ITimeGraphEntry { private TimeGraphEntry fParent = null; /** List of child entries */ - private final List fChildren = new ArrayList<>(); + private final List fChildren = new CopyOnWriteArrayList<>(); /** Name of this entry (text to show) */ private String fName; @@ -106,6 +107,18 @@ public class TimeGraphEntry implements ITimeGraphEntry { return fEndTime; } + /** + * Updates the end time + * + * @param endTime + * the end time + * + * @since 3.0 + */ + public void updateEndTime(long endTime) { + fEndTime = Math.max(endTime, fEndTime); + } + @Override public boolean hasTimeEvents() { return true; @@ -129,16 +142,22 @@ public class TimeGraphEntry implements ITimeGraphEntry { /** * Add an event to this entry's event list. If necessary, update the start - * and end time of the entry. + * and end time of the entry. If the event list's last event starts at the + * same time as the event to add, it is replaced by the new event. * * @param event - * The time event + * The time event to add */ public void addEvent(ITimeEvent event) { long start = event.getTime(); long end = start + event.getDuration(); synchronized (fEventList) { - fEventList.add(event); + int lastIndex = fEventList.size() - 1; + if (lastIndex >= 0 && fEventList.get(lastIndex).getTime() == event.getTime()) { + fEventList.set(lastIndex, event); + } else { + fEventList.add(event); + } if (fStartTime == -1 || start < fStartTime) { fStartTime = start; } -- 2.34.1