From: Bernd Hufmann Date: Tue, 22 Mar 2016 11:29:09 +0000 (-0400) Subject: analysis: Bug 489573: Internalize Resources view implementation X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=eeff806b38531e9d07bdcdc9cca78f3242f6d10b;p=deliverable%2Ftracecompass.git analysis: Bug 489573: Internalize Resources view implementation Change-Id: I35fc6e359b2727b19ad77e5788bb9e7c0f1dfb51 Signed-off-by: Bernd Hufmann Reviewed-on: https://git.eclipse.org/r/69008 Reviewed-by: Hudson CI Reviewed-by: Matthew Khouzam Tested-by: Matthew Khouzam --- diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/resources/AggregateIteratorTest.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/resources/AggregateIteratorTest.java index 97b0ef0d74..3bed8c17ba 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/resources/AggregateIteratorTest.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/resources/AggregateIteratorTest.java @@ -18,7 +18,7 @@ import java.util.List; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.tracecompass.analysis.os.linux.ui.views.resources.AggregateEventIterator; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.AggregateEventIterator; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent; diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF index 2d3907dfbb..d7b1547389 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF @@ -24,7 +24,6 @@ Import-Package: com.google.common.base, com.google.common.collect, org.swtchart Export-Package: org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow, - org.eclipse.tracecompass.analysis.os.linux.ui.views.resources, org.eclipse.tracecompass.internal.analysis.os.linux.ui;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", org.eclipse.tracecompass.internal.analysis.os.linux.ui.actions;x-internal:=true, org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests,org.eclipse.tracecompass.analysis.os.linux.ui.tests", @@ -33,4 +32,8 @@ Export-Package: org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow, org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.cpuusage;x-internal:=true, org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.statistics;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", - org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests" + org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources; + x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests, + org.eclipse.tracecompass.analysis.os.linux.ui.tests, + org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests, + org.eclipse.tracecompass.lttng2.kernel.ui" diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml index 00275929c6..d650f818b7 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/plugin.xml @@ -15,7 +15,7 @@ { - - private final List<@NonNull CachingIterator> fIterators = new ArrayList<>(); - - private final Comparator fComparator; - - /** - * Constructor - * - * @param contributors - * the entries to aggregate - * @param comparator - * The comparator to sort time events - */ - public AggregateEventIterator(@NonNull List contributors, Comparator comparator) { - this(contributors, Long.MIN_VALUE, Long.MAX_VALUE, 1, comparator); - } - - /** - * Constructor with a time range - * - * @param contributors - * the entries to aggregate - * @param startTime - * start time in nanoseconds - * @param endTime - * stop time in nanoseconds - * @param duration - * duration of one pixel in nanoseconds - * @param comparator - * The comparator to sort time events - */ - public AggregateEventIterator(@NonNull List contributors, long startTime, long endTime, long duration, Comparator comparator) { - fComparator = comparator; - contributors.forEach(timeGraphEntry -> { - final Iterator<@NonNull ITimeEvent> timeEventsIterator = timeGraphEntry.getTimeEventsIterator(startTime, endTime, duration); - if (timeEventsIterator != null) { - CachingIterator iterator = new CachingIterator(timeEventsIterator, comparator); - if (iterator.hasNext()) { - fIterators.add(iterator); - } - } - }); - } - - @Override - public boolean hasNext() { - return !fIterators.isEmpty(); - } - - @Override - public @NonNull ITimeEvent next() { - - final List<@NonNull CachingIterator> iterators = fIterators; - if (iterators.isEmpty()) { - throw new NoSuchElementException("Aggregate iterator is empty"); //$NON-NLS-1$ - } - - ITimeEvent winner = iterators.get(0).peek(); - long trimTime = winner.getTime() + winner.getDuration(); - for (int i = 1; i < iterators.size(); i++) { - CachingIterator iterator = iterators.get(i); - ITimeEvent candidate = iterator.peek(); - if (candidate.getTime() < winner.getTime()) { - trimTime = Math.min(winner.getTime(), candidate.getTime() + candidate.getDuration()); - winner = candidate; - } else if (candidate.getTime() == winner.getTime()) { - trimTime = Math.min(trimTime, candidate.getTime() + candidate.getDuration()); - if (fComparator.compare(candidate, winner) < 0) { - winner = candidate; - } - } else { - trimTime = Math.min(trimTime, candidate.getTime()); - } - } - - /* Trim the next event before the trim time, if necessary. */ - final ITimeEvent next = (trimTime < (winner.getDuration() + winner.getTime())) ? winner.splitBefore(trimTime) : winner; - - /* Trim all remaining events after the trim time, if necessary. */ - Iterator iteratorIterator = iterators.iterator(); - while (iteratorIterator.hasNext()) { - CachingIterator iterator = iteratorIterator.next(); - iterator.trim(trimTime); - /* Remove empty iterators from the list */ - if (!iterator.hasNext()) { - iteratorIterator.remove(); - } - } - - return checkNotNull(next); - } -} \ No newline at end of file diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateResourcesEntry.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateResourcesEntry.java deleted file mode 100644 index eb41383827..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateResourcesEntry.java +++ /dev/null @@ -1,106 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 Ericsson - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v1.0 which - * accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ - -package org.eclipse.tracecompass.analysis.os.linux.ui.views.resources; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; - -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; -import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent; - -/** - * Internal entry of the aggregate kind, it is one without a state system value, - * it uses other entries and aggregates their values. - * - * @author Matthew Khouzam - */ -class AggregateResourcesEntry extends ResourcesEntry { - - private final @NonNull List fContributors = new ArrayList<>(); - - private static final Comparator COMPARATOR = new Comparator() { - @Override - public int compare(ITimeEvent o1, ITimeEvent o2) { - // largest value - return Integer.compare(getValue(o2), getValue(o1)); - } - - private int getValue(ITimeEvent element) { - return (element instanceof TimeEvent) ? ((TimeEvent) element).getValue() : Integer.MIN_VALUE; - } - }; - - /** - * AggregateResourcesEntry Constructor - * - * @param trace - * the parent trace - * @param startTime - * the start time - * @param endTime - * the end time - * @param type - * the type - * @param id - * the id - */ - public AggregateResourcesEntry(@NonNull ITmfTrace trace, - long startTime, long endTime, Type type, int id) { - super(ITmfStateSystem.INVALID_ATTRIBUTE, trace, startTime, endTime, type, id); - } - - /** - * Constructor - * - * @param trace - * The trace on which we are working - * @param name - * The exec_name of this entry - * @param startTime - * The start time of this entry lifetime - * @param endTime - * The end time of this entry - * @param type - * The type of this entry - * @param id - * The id of this entry - */ - public AggregateResourcesEntry(@NonNull ITmfTrace trace, String name, long startTime, long endTime, Type type, int id) { - super(ITmfStateSystem.INVALID_ATTRIBUTE, trace, name, startTime, endTime, type, id); - } - - @Override - public void addEvent(ITimeEvent event) { - } - - @Override - public void addZoomedEvent(ITimeEvent event) { - } - - @Override - public Iterator<@NonNull ITimeEvent> getTimeEventsIterator() { - return new AggregateEventIterator(fContributors, COMPARATOR); - } - - @Override - public Iterator<@NonNull ITimeEvent> getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) { - return new AggregateEventIterator(fContributors, startTime, stopTime, visibleDuration, COMPARATOR); - } - - public void addContributor(ITimeGraphEntry entry) { - fContributors.add(entry); - } -} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/CachingIterator.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/CachingIterator.java deleted file mode 100644 index 46c4b6b1d5..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/CachingIterator.java +++ /dev/null @@ -1,90 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 Ericsson - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v1.0 which - * accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ - -package org.eclipse.tracecompass.analysis.os.linux.ui.views.resources; - -import java.util.Comparator; -import java.util.Iterator; -import java.util.NoSuchElementException; - -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; - -/** - * Caching iterator of time events with a couple extras. - *
    - *
  • peek() allows reading the head without removing it
  • - *
  • trim() allows removing a bit of the first event
  • - *
- * - * @author Matthew Khouzam - */ -class CachingIterator implements Iterator<@NonNull ITimeEvent>, Comparable { - private ITimeEvent fEvent; - private @NonNull Iterator<@NonNull ? extends ITimeEvent> fIterator; - private final Comparator fComparator; - - public CachingIterator(@NonNull Iterator<@NonNull ? extends ITimeEvent> iterator, Comparator comparator) { - fIterator = iterator; - fComparator = comparator; - fEvent = iterator.hasNext() ? iterator.next() : null; - } - - @Override - public ITimeEvent next() { - ITimeEvent retVal = fEvent; - fEvent = fIterator.hasNext() ? fIterator.next() : null; - if (retVal == null) { - throw new NoSuchElementException("Iterator is empty"); //$NON-NLS-1$ - } - return retVal; - } - - @Override - public boolean hasNext() { - return fEvent != null; - } - - /** - * Retrieves, but does not remove, the next element of this iterator, or - * returns {@code null} if this iterator does not have a next. - * - * @return the next element of the iterator - */ - public ITimeEvent peek() { - return fEvent; - } - - @Override - public int compareTo(CachingIterator o) { - final ITimeEvent myEvent = peek(); - final ITimeEvent otherEvent = o.peek(); - return fComparator.compare(myEvent, otherEvent); - } - - /** - * Trims the next element in the iterator to be after a cut-off time. - * - * @param time - * the cut-off time - * @return true if there was a trim - */ - public boolean trim(long time) { - if (time <= fEvent.getTime()) { - return false; - } - if (time < fEvent.getTime() + fEvent.getDuration()) { - fEvent = fEvent.splitAfter(time); - return true; - } - fEvent = fIterator.hasNext() ? fIterator.next() : null; - return true; - } - -} \ No newline at end of file diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesEntry.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesEntry.java deleted file mode 100644 index 8e1a128926..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesEntry.java +++ /dev/null @@ -1,195 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012, 2015 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 - * accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Patrick Tasse - Initial API and implementation - * Geneviève Bastien - Move code to provide base classes for time graph view - *******************************************************************************/ - -package org.eclipse.tracecompass.analysis.os.linux.ui.views.resources; - -import java.util.Iterator; - -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.SoftIrqLabelProvider; -import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry; - -/** - * An entry, or row, in the resource view - * - * @author Patrick Tasse - */ -public class ResourcesEntry extends TimeGraphEntry implements Comparable { - - /** Type of resource */ - public static enum Type { - /** Null resources (filler rows, etc.) */ - NULL, - /** Entries for CPUs */ - CPU, - /** Entries for IRQs */ - IRQ, - /** Entries for Soft IRQ */ - SOFT_IRQ - } - - private final int fId; - private final @NonNull ITmfTrace fTrace; - private final Type fType; - private final int fQuark; - - /** - * Constructor - * - * @param quark - * The attribute quark matching the entry - * @param trace - * The trace on which we are working - * @param name - * The exec_name of this entry - * @param startTime - * The start time of this entry lifetime - * @param endTime - * The end time of this entry - * @param type - * The type of this entry - * @param id - * The id of this entry - */ - public ResourcesEntry(int quark, @NonNull ITmfTrace trace, String name, - long startTime, long endTime, Type type, int id) { - super(name, startTime, endTime); - fId = id; - fTrace = trace; - fType = type; - fQuark = quark; - } - - /** - * Constructor - * - * @param trace - * The trace on which we are working - * @param name - * The exec_name of this entry - * @param startTime - * The start time of this entry lifetime - * @param endTime - * The end time of this entry - * @param id - * The id of this entry - */ - public ResourcesEntry(@NonNull ITmfTrace trace, String name, - long startTime, long endTime, int id) { - this(-1, trace, name, startTime, endTime, Type.NULL, id); - } - - /** - * Constructor - * - * @param quark - * The attribute quark matching the entry - * @param trace - * The trace on which we are working - * @param startTime - * The start time of this entry lifetime - * @param endTime - * The end time of this entry - * @param type - * The type of this entry - * @param id - * The id of this entry - */ - public ResourcesEntry(int quark, @NonNull ITmfTrace trace, - long startTime, long endTime, Type type, int id) { - this(quark, trace, computeEntryName(type, id), startTime, endTime, type, id); - } - - private static String computeEntryName(Type type, int id) { - if (Type.SOFT_IRQ.equals(type)) { - return type.toString() + ' ' + id + ' ' + SoftIrqLabelProvider.getSoftIrq(id); - } - return type.toString() + ' ' + id; - } - - /** - * Get the entry's id - * - * @return the entry's id - */ - public int getId() { - return fId; - } - - /** - * Get the entry's trace - * - * @return the entry's trace - */ - public @NonNull ITmfTrace getTrace() { - return fTrace; - } - - /** - * Get the entry Type of this entry. Uses the inner Type enum. - * - * @return The entry type - */ - public Type getType() { - return fType; - } - - /** - * Retrieve the attribute quark that's represented by this entry. - * - * @return The integer quark The attribute quark matching the entry - */ - public int getQuark() { - return fQuark; - } - - @Override - public boolean hasTimeEvents() { - if (fType == Type.NULL) { - return false; - } - return true; - } - - @Override - public int compareTo(ITimeGraphEntry other) { - if (!(other instanceof ResourcesEntry)) { - /* - * Should not happen, but if it does, put those entries at the end - */ - return -1; - } - ResourcesEntry o = (ResourcesEntry) other; - - /* - * Resources entry names should all be of type "ABC 123" - * - * We want to filter on the Type first (the "ABC" part), then on the ID - * ("123") in numerical order (so we get 1,2,10 and not 1,10,2). - */ - int ret = this.getType().compareTo(o.getType()); - if (ret != 0) { - return ret; - } - return Integer.compare(this.getId(), o.getId()); - } - - @Override - public Iterator<@NonNull ITimeEvent> getTimeEventsIterator() { - return super.getTimeEventsIterator(); - } - -} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesPresentationProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesPresentationProvider.java deleted file mode 100644 index cf3ab585e1..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesPresentationProvider.java +++ /dev/null @@ -1,379 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012, 2015 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 - * accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Patrick Tasse - Initial API and implementation - * Geneviève Bastien - Move code to provide base classes for time graph view - *******************************************************************************/ - -package org.eclipse.tracecompass.analysis.os.linux.ui.views.resources; - -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule; -import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues; -import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout; -import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace; -import org.eclipse.tracecompass.analysis.os.linux.ui.views.resources.ResourcesEntry.Type; -import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes; -import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator; -import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages; -import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; -import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; -import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; -import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException; -import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; -import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; -import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; -import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; -import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.StateItem; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.ITmfTimeGraphDrawingHelper; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.Resolution; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat; - -/** - * Presentation provider for the Resource view, based on the generic TMF - * presentation provider. - * - * @author Patrick Tasse - */ -public class ResourcesPresentationProvider extends TimeGraphPresentationProvider { - - private long fLastThreadId = -1; - private Color fColorWhite; - private Color fColorGray; - private Integer fAverageCharWidth; - - private enum State { - IDLE (new RGB(200, 200, 200)), - USERMODE (new RGB( 0, 200, 0)), - SYSCALL (new RGB( 0, 0, 200)), - IRQ (new RGB(200, 0, 100)), - SOFT_IRQ (new RGB(200, 150, 100)), - IRQ_ACTIVE (new RGB(200, 0, 100)), - SOFT_IRQ_RAISED (new RGB(200, 200, 0)), - SOFT_IRQ_ACTIVE (new RGB(200, 150, 100)); - - public final RGB rgb; - - private State(RGB rgb) { - this.rgb = rgb; - } - } - - /** - * Default constructor - */ - public ResourcesPresentationProvider() { - super(); - } - - private static State[] getStateValues() { - return State.values(); - } - - private static State getEventState(TimeEvent event) { - if (event.hasValue()) { - ResourcesEntry entry = (ResourcesEntry) event.getEntry(); - int value = event.getValue(); - - if (entry.getType() == Type.CPU) { - if (value == StateValues.CPU_STATUS_IDLE) { - return State.IDLE; - } else if (value == StateValues.CPU_STATUS_RUN_USERMODE) { - return State.USERMODE; - } else if (value == StateValues.CPU_STATUS_RUN_SYSCALL) { - return State.SYSCALL; - } else if (value == StateValues.CPU_STATUS_IRQ) { - return State.IRQ; - } else if (value == StateValues.CPU_STATUS_SOFTIRQ) { - return State.SOFT_IRQ; - } - } else if (entry.getType() == Type.IRQ) { - return State.IRQ_ACTIVE; - } else if (entry.getType() == Type.SOFT_IRQ) { - if (value == StateValues.CPU_STATUS_SOFT_IRQ_RAISED) { - return State.SOFT_IRQ_RAISED; - } - return State.SOFT_IRQ_ACTIVE; - } - } - return null; - } - - @Override - public int getStateTableIndex(ITimeEvent event) { - State state = getEventState((TimeEvent) event); - if (state != null) { - return state.ordinal(); - } - if (event instanceof NullTimeEvent) { - return INVISIBLE; - } - return TRANSPARENT; - } - - @Override - public StateItem[] getStateTable() { - State[] states = getStateValues(); - StateItem[] stateTable = new StateItem[states.length]; - for (int i = 0; i < stateTable.length; i++) { - State state = states[i]; - stateTable[i] = new StateItem(state.rgb, state.toString()); - } - return stateTable; - } - - @Override - public String getEventName(ITimeEvent event) { - State state = getEventState((TimeEvent) event); - if (state != null) { - return state.toString(); - } - if (event instanceof NullTimeEvent) { - return null; - } - return Messages.ResourcesView_multipleStates; - } - - @Override - public Map getEventHoverToolTipInfo(ITimeEvent event, long hoverTime) { - - Map retMap = new LinkedHashMap<>(); - if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) { - - TimeEvent tcEvent = (TimeEvent) event; - ResourcesEntry entry = (ResourcesEntry) event.getEntry(); - - if (tcEvent.hasValue()) { - ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID); - if (ss == null) { - return retMap; - } - // Check for IRQ or Soft_IRQ type - if (entry.getType().equals(Type.IRQ) || entry.getType().equals(Type.SOFT_IRQ)) { - - // Get CPU of IRQ or SoftIRQ and provide it for the tooltip display - int cpu = tcEvent.getValue(); - if (cpu >= 0) { - retMap.put(Messages.ResourcesView_attributeCpuName, String.valueOf(cpu)); - } - } - - // Check for type CPU - else if (entry.getType().equals(Type.CPU)) { - int status = tcEvent.getValue(); - - if (status == StateValues.CPU_STATUS_IRQ) { - // In IRQ state get the IRQ that caused the interruption - int cpu = entry.getId(); - - try { - List fullState = ss.queryFullState(event.getTime()); - List irqQuarks = ss.getQuarks(Attributes.CPUS, Integer.toString(cpu), Attributes.IRQS, "*"); //$NON-NLS-1$ - - for (int irqQuark : irqQuarks) { - if (fullState.get(irqQuark).getStateValue().unboxInt() == cpu) { - ITmfStateInterval value = ss.querySingleState(event.getTime(), irqQuark); - if (!value.getStateValue().isNull()) { - int irq = Integer.parseInt(ss.getAttributeName(irqQuark)); - retMap.put(Messages.ResourcesView_attributeIrqName, String.valueOf(irq)); - } - break; - } - } - } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) { - Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$ - } catch (StateSystemDisposedException e) { - /* Ignored */ - } - } else if (status == StateValues.CPU_STATUS_SOFTIRQ) { - // In SOFT_IRQ state get the SOFT_IRQ that caused the interruption - int cpu = entry.getId(); - - try { - List fullState = ss.queryFullState(event.getTime()); - List softIrqQuarks = ss.getQuarks(Attributes.CPUS, Integer.toString(cpu), Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$ - - for (int softIrqQuark : softIrqQuarks) { - if (fullState.get(softIrqQuark).getStateValue().unboxInt() == cpu) { - ITmfStateInterval value = ss.querySingleState(event.getTime(), softIrqQuark); - if (!value.getStateValue().isNull()) { - int softIrq = Integer.parseInt(ss.getAttributeName(softIrqQuark)); - retMap.put(Messages.ResourcesView_attributeSoftIrqName, String.valueOf(softIrq)); - } - break; - } - } - } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) { - Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$ - } catch (StateSystemDisposedException e) { - /* Ignored */ - } - } else if (status == StateValues.CPU_STATUS_RUN_USERMODE || status == StateValues.CPU_STATUS_RUN_SYSCALL) { - // In running state get the current tid - - try { - retMap.put(Messages.ResourcesView_attributeHoverTime, Utils.formatTime(hoverTime, TimeFormat.CALENDAR, Resolution.NANOSEC)); - int cpuQuark = entry.getQuark(); - int currentThreadQuark = ss.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD); - ITmfStateInterval interval = ss.querySingleState(hoverTime, currentThreadQuark); - if (!interval.getStateValue().isNull()) { - ITmfStateValue value = interval.getStateValue(); - int currentThreadId = value.unboxInt(); - retMap.put(Messages.ResourcesView_attributeTidName, Integer.toString(currentThreadId)); - int execNameQuark = ss.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.EXEC_NAME); - interval = ss.querySingleState(hoverTime, execNameQuark); - if (!interval.getStateValue().isNull()) { - value = interval.getStateValue(); - retMap.put(Messages.ResourcesView_attributeProcessName, value.unboxStr()); - } - if (status == StateValues.CPU_STATUS_RUN_SYSCALL) { - int syscallQuark = ss.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.SYSTEM_CALL); - interval = ss.querySingleState(hoverTime, syscallQuark); - if (!interval.getStateValue().isNull()) { - value = interval.getStateValue(); - retMap.put(Messages.ResourcesView_attributeSyscallName, value.unboxStr()); - } - } - } - } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) { - Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$ - } catch (StateSystemDisposedException e) { - /* Ignored */ - } - } - } - } - } - - return retMap; - } - - @Override - public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) { - if (fColorGray == null) { - fColorGray = gc.getDevice().getSystemColor(SWT.COLOR_GRAY); - } - if (fColorWhite == null) { - fColorWhite = gc.getDevice().getSystemColor(SWT.COLOR_WHITE); - } - if (fAverageCharWidth == null) { - fAverageCharWidth = gc.getFontMetrics().getAverageCharWidth(); - } - - ITmfTimeGraphDrawingHelper drawingHelper = getDrawingHelper(); - if (bounds.width <= fAverageCharWidth) { - return; - } - - if (!(event instanceof TimeEvent)) { - return; - } - TimeEvent tcEvent = (TimeEvent) event; - if (!tcEvent.hasValue()) { - return; - } - - ResourcesEntry entry = (ResourcesEntry) event.getEntry(); - if (!entry.getType().equals(Type.CPU)) { - return; - } - - int status = tcEvent.getValue(); - if (status != StateValues.CPU_STATUS_RUN_USERMODE && status != StateValues.CPU_STATUS_RUN_SYSCALL) { - return; - } - - ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID); - if (ss == null) { - return; - } - long time = event.getTime(); - try { - while (time < event.getTime() + event.getDuration()) { - int cpuQuark = entry.getQuark(); - int currentThreadQuark = ss.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD); - ITmfStateInterval tidInterval = ss.querySingleState(time, currentThreadQuark); - long startTime = Math.max(tidInterval.getStartTime(), event.getTime()); - int x = Math.max(drawingHelper.getXForTime(startTime), bounds.x); - if (x >= bounds.x + bounds.width) { - break; - } - if (!tidInterval.getStateValue().isNull()) { - ITmfStateValue value = tidInterval.getStateValue(); - int currentThreadId = value.unboxInt(); - long endTime = Math.min(tidInterval.getEndTime() + 1, event.getTime() + event.getDuration()); - int xForEndTime = drawingHelper.getXForTime(endTime); - if (xForEndTime > bounds.x) { - int width = Math.min(xForEndTime, bounds.x + bounds.width) - x - 1; - if (width > 0) { - String attribute = null; - int beginIndex = 0; - if (status == StateValues.CPU_STATUS_RUN_USERMODE && currentThreadId != fLastThreadId) { - attribute = Attributes.EXEC_NAME; - } else if (status == StateValues.CPU_STATUS_RUN_SYSCALL) { - attribute = Attributes.SYSTEM_CALL; - /* - * Remove the "sys_" or "syscall_entry_" or similar from what we - * draw in the rectangle. This depends on the trace's event layout. - */ - ITmfTrace trace = entry.getTrace(); - if (trace instanceof IKernelTrace) { - IKernelAnalysisEventLayout layout = ((IKernelTrace) trace).getKernelEventLayout(); - beginIndex = layout.eventSyscallEntryPrefix().length(); - } - } - if (attribute != null) { - int quark = ss.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), attribute); - ITmfStateInterval interval = ss.querySingleState(time, quark); - if (!interval.getStateValue().isNull()) { - value = interval.getStateValue(); - gc.setForeground(fColorWhite); - int drawn = Utils.drawText(gc, value.unboxStr().substring(beginIndex), x + 1, bounds.y, width, bounds.height, true, true); - if (drawn > 0 && status == StateValues.CPU_STATUS_RUN_USERMODE) { - fLastThreadId = currentThreadId; - } - } - } - if (xForEndTime < bounds.x + bounds.width) { - gc.setForeground(fColorGray); - gc.drawLine(xForEndTime, bounds.y + 1, xForEndTime, bounds.y + bounds.height - 2); - } - } - } - } - // make sure next time is at least at the next pixel - time = Math.max(tidInterval.getEndTime() + 1, drawingHelper.getTimeAtX(x + 1)); - } - } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) { - Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$ - } catch (StateSystemDisposedException e) { - /* Ignored */ - } - } - - @Override - public void postDrawEntry(ITimeGraphEntry entry, Rectangle bounds, GC gc) { - fLastThreadId = -1; - } -} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesView.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesView.java deleted file mode 100644 index fe4edbd3cd..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesView.java +++ /dev/null @@ -1,450 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012, 2016 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 - * accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Patrick Tasse - Initial API and implementation - * Geneviève Bastien - Move code to provide base classes for time graph views - *******************************************************************************/ - -package org.eclipse.tracecompass.analysis.os.linux.ui.views.resources; - -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.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule; -import org.eclipse.tracecompass.analysis.os.linux.core.signals.TmfCpuSelectedSignal; -import org.eclipse.tracecompass.analysis.os.linux.ui.views.resources.ResourcesEntry.Type; -import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes; -import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages; -import org.eclipse.tracecompass.internal.analysis.os.linux.ui.actions.FollowCpuAction; -import org.eclipse.tracecompass.internal.analysis.os.linux.ui.actions.UnfollowCpuAction; -import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; -import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; -import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; -import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; -import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; -import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; -import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractStateSystemTimeGraphView; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent; -import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry; - -/** - * Main implementation for the LTTng 2.0 kernel Resource view - * - * @author Patrick Tasse - */ -public class ResourcesView extends AbstractStateSystemTimeGraphView { - - /** View ID. */ - public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.resources"; //$NON-NLS-1$ - - private static final String[] FILTER_COLUMN_NAMES = new String[] { - Messages.ResourcesView_stateTypeName - }; - - private int fCurrentCpu = -1; - - // Timeout between updates in the build thread in ms - private static final long BUILD_UPDATE_TIMEOUT = 500; - - // ------------------------------------------------------------------------ - // Constructors - // ------------------------------------------------------------------------ - - /** - * Default constructor - */ - public ResourcesView() { - super(ID, new ResourcesPresentationProvider()); - setFilterColumns(FILTER_COLUMN_NAMES); - setFilterLabelProvider(new ResourcesFilterLabelProvider()); - setEntryComparator(new ResourcesEntryComparator()); - setAutoExpandLevel(1); - } - - private static class ResourcesEntryComparator implements Comparator { - @Override - public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) { - ResourcesEntry entry1 = (ResourcesEntry) o1; - ResourcesEntry entry2 = (ResourcesEntry) o2; - if (entry1.getType() == Type.NULL && entry2.getType() == Type.NULL) { - /* sort trace entries alphabetically */ - return entry1.getName().compareTo(entry2.getName()); - } - /* sort resource entries by their defined order */ - return entry1.compareTo(entry2); - } - } - - - /** - * @since 2.0 - */ - @Override - protected void fillTimeGraphEntryContextMenu(@NonNull IMenuManager menuManager) { - ISelection selection = getSite().getSelectionProvider().getSelection(); - if (selection instanceof IStructuredSelection) { - IStructuredSelection sSel = (IStructuredSelection) selection; - if (sSel.getFirstElement() instanceof ResourcesEntry) { - ResourcesEntry resourcesEntry = (ResourcesEntry) sSel.getFirstElement(); - if (resourcesEntry.getType().equals(ResourcesEntry.Type.CPU)) { - if (fCurrentCpu >= 0) { - menuManager.add(new UnfollowCpuAction(ResourcesView.this, resourcesEntry.getId(), resourcesEntry.getTrace())); - } else { - menuManager.add(new FollowCpuAction(ResourcesView.this, resourcesEntry.getId(), resourcesEntry.getTrace())); - } - } - } - } - } - - private static class ResourcesFilterLabelProvider extends TreeLabelProvider { - @Override - public String getColumnText(Object element, int columnIndex) { - ResourcesEntry entry = (ResourcesEntry) element; - if (columnIndex == 0) { - return entry.getName(); - } - return ""; //$NON-NLS-1$ - } - - } - - // ------------------------------------------------------------------------ - // Internal - // ------------------------------------------------------------------------ - - @Override - protected String getNextText() { - return Messages.ResourcesView_nextResourceActionNameText; - } - - @Override - protected String getNextTooltip() { - return Messages.ResourcesView_nextResourceActionToolTipText; - } - - @Override - protected String getPrevText() { - return Messages.ResourcesView_previousResourceActionNameText; - } - - @Override - protected String getPrevTooltip() { - return Messages.ResourcesView_previousResourceActionToolTipText; - } - - @Override - protected void buildEntryList(ITmfTrace trace, ITmfTrace parentTrace, final IProgressMonitor monitor) { - final ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID); - if (ssq == null) { - return; - } - - 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; - } - 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, ssq, entryList); - } else { - traceEntry.updateEndTime(endTime); - } - List cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$ - createCpuEntriesWithQuark(trace, ssq, entryMap, traceEntry, startTime, endTime, cpuQuarks); - if (parentTrace.equals(getTrace())) { - refresh(); - } - final List<@NonNull TimeGraphEntry> traceEntryChildren = traceEntry.getChildren(); - final long resolution = Math.max(1, (endTime - ssq.getStartTime()) / getDisplayWidth()); - queryFullStates(ssq, ssq.getStartTime(), end, resolution, monitor, new IQueryHandler() { - @Override - public void handle(List> fullStates, List prevFullState) { - for (TimeGraphEntry child : traceEntryChildren) { - if (!populateEventsRecursively(fullStates, prevFullState, child).isOK()) { - return; - } - } - } - - private IStatus populateEventsRecursively(@NonNull List> fullStates, @Nullable List prevFullState, @NonNull TimeGraphEntry entry) { - if (monitor.isCanceled()) { - return Status.CANCEL_STATUS; - } - List eventList = getEventList(entry, ssq, fullStates, prevFullState, monitor); - if (eventList != null) { - /* Start a new event list on first iteration, then append to it */ - if (prevFullState == null) { - entry.setEventList(eventList); - } else { - for (ITimeEvent event : eventList) { - entry.addEvent(event); - } - } - } - for (TimeGraphEntry child : entry.getChildren()) { - IStatus status = populateEventsRecursively(fullStates, prevFullState, child); - if (!status.isOK()) { - return status; - } - } - return Status.OK_STATUS; - } - }); - - start = end; - } - - } - - private static void createCpuEntriesWithQuark(@NonNull ITmfTrace trace, final ITmfStateSystem ssq, Map entryMap, TimeGraphEntry traceEntry, long startTime, long endTime, List cpuQuarks) { - for (Integer cpuQuark : cpuQuarks) { - final @NonNull String cpuName = ssq.getAttributeName(cpuQuark); - int cpu = Integer.parseInt(cpuName); - ResourcesEntry cpuEntry = entryMap.get(cpuQuark); - if (cpuEntry == null) { - cpuEntry = new ResourcesEntry(cpuQuark, trace, startTime, endTime, Type.CPU, cpu); - entryMap.put(cpuQuark, cpuEntry); - traceEntry.addChild(cpuEntry); - } else { - cpuEntry.updateEndTime(endTime); - } - List irqQuarks = ssq.getQuarks(Attributes.CPUS, cpuName, Attributes.IRQS, "*"); //$NON-NLS-1$ - createCpuInterruptEntryWithQuark(trace, ssq, entryMap, startTime, endTime, traceEntry, cpuEntry, irqQuarks, Type.IRQ); - List softIrqQuarks = ssq.getQuarks(Attributes.CPUS, cpuName, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$ - createCpuInterruptEntryWithQuark(trace, ssq, entryMap, startTime, endTime, traceEntry, cpuEntry, softIrqQuarks, Type.SOFT_IRQ); - } - } - - /** - * Create and add execution contexts to a cpu entry. Also creates an - * aggregate entry in the root trace entry. The execution context is - * basically what the cpu is doing in its execution stack. It can be in an - * IRQ, Soft IRQ. MCEs, NMIs, Userland and Kernel execution is not yet - * supported. - * - * @param trace - * the trace - * @param ssq - * the state system - * @param entryMap - * the entry map - * @param startTime - * the start time in nanoseconds - * @param endTime - * the end time in nanoseconds - * @param traceEntry - * the trace timegraph entry - * @param cpuEntry - * the cpu timegraph entry (the entry under the trace entry - * @param childrenQuarks - * the quarks to add to cpu entry - * @param type - * the type of entry being added - */ - private static void createCpuInterruptEntryWithQuark(@NonNull ITmfTrace trace, - final ITmfStateSystem ssq, Map entryMap, - long startTime, long endTime, - TimeGraphEntry traceEntry, ResourcesEntry cpuEntry, - List childrenQuarks, Type type) { - for (Integer quark : childrenQuarks) { - final @NonNull String resourceName = ssq.getAttributeName(quark); - int resourceId = Integer.parseInt(resourceName); - ResourcesEntry interruptEntry = entryMap.get(quark); - if (interruptEntry == null) { - interruptEntry = new ResourcesEntry(quark, trace, startTime, endTime, type, resourceId); - entryMap.put(quark, interruptEntry); - cpuEntry.addChild(interruptEntry); - boolean found = false; - for (ITimeGraphEntry rootElem : traceEntry.getChildren()) { - if (rootElem instanceof AggregateResourcesEntry) { - AggregateResourcesEntry aggregateInterruptEntry = (AggregateResourcesEntry) rootElem; - if (aggregateInterruptEntry.getId() == resourceId && aggregateInterruptEntry.getType().equals(type)) { - found = true; - aggregateInterruptEntry.addContributor(interruptEntry); - final AggregateResourcesEntry irqCpuEntry = new AggregateResourcesEntry(trace, cpuEntry.getName(), startTime, endTime, type, cpuEntry.getId()); - irqCpuEntry.addContributor(interruptEntry); - aggregateInterruptEntry.addChild(irqCpuEntry); - break; - } - } - } - if (!found) { - AggregateResourcesEntry aggregateInterruptEntry = new AggregateResourcesEntry(trace, startTime, endTime, type, resourceId); - aggregateInterruptEntry.addContributor(interruptEntry); - final AggregateResourcesEntry irqCpuEntry = new AggregateResourcesEntry(trace, cpuEntry.getName(), startTime, endTime, type, cpuEntry.getId()); - irqCpuEntry.addContributor(interruptEntry); - aggregateInterruptEntry.addChild(irqCpuEntry); - traceEntry.addChild(aggregateInterruptEntry); - } - } else { - interruptEntry.updateEndTime(endTime); - } - } - } - - @Override - protected @Nullable List getEventList(@NonNull TimeGraphEntry entry, ITmfStateSystem ssq, - @NonNull List> fullStates, @Nullable List prevFullState, @NonNull IProgressMonitor monitor) { - ResourcesEntry resourcesEntry = (ResourcesEntry) entry; - int quark = resourcesEntry.getQuark(); - - if (resourcesEntry.getType().equals(Type.CPU)) { - return createCpuEventsList(entry, ssq, fullStates, prevFullState, monitor, quark); - } else if ((resourcesEntry.getType().equals(Type.IRQ) || resourcesEntry.getType().equals(Type.SOFT_IRQ)) && (quark >= 0)) { - return createIrqEventsList(entry, fullStates, prevFullState, monitor, quark); - } - - return null; - } - - private static List createCpuEventsList(ITimeGraphEntry entry, ITmfStateSystem ssq, List> fullStates, List prevFullState, IProgressMonitor monitor, int quark) { - List eventList; - int statusQuark; - try { - statusQuark = ssq.getQuarkRelative(quark, Attributes.STATUS); - } catch (AttributeNotFoundException e) { - /* - * The sub-attribute "status" is not available. May happen if the - * trace does not have sched_switch events enabled. - */ - return null; - } - boolean isZoomThread = Thread.currentThread() instanceof ZoomThread; - eventList = new ArrayList<>(fullStates.size()); - ITmfStateInterval lastInterval = prevFullState == null || statusQuark >= prevFullState.size() ? null : prevFullState.get(statusQuark); - long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime(); - long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1; - for (List fullState : fullStates) { - if (monitor.isCanceled()) { - return null; - } - if (statusQuark >= fullState.size()) { - /* No information on this CPU (yet?), skip it for now */ - continue; - } - ITmfStateInterval statusInterval = fullState.get(statusQuark); - int status = statusInterval.getStateValue().unboxInt(); - long time = statusInterval.getStartTime(); - long duration = statusInterval.getEndTime() - time + 1; - if (time == lastStartTime) { - continue; - } - if (!statusInterval.getStateValue().isNull()) { - if (lastEndTime != time && lastEndTime != -1) { - eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime)); - } - eventList.add(new TimeEvent(entry, time, duration, status)); - } else if (isZoomThread) { - eventList.add(new NullTimeEvent(entry, time, duration)); - } - lastStartTime = time; - lastEndTime = time + duration; - } - return eventList; - } - - private static List createIrqEventsList(ITimeGraphEntry entry, List> fullStates, List prevFullState, IProgressMonitor monitor, int quark) { - List eventList; - boolean isZoomThread = Thread.currentThread() instanceof ZoomThread; - eventList = new ArrayList<>(fullStates.size()); - ITmfStateInterval lastInterval = prevFullState == null || quark >= prevFullState.size() ? null : prevFullState.get(quark); - long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime(); - long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1; - boolean lastIsNull = lastInterval == null ? false : lastInterval.getStateValue().isNull(); - for (List fullState : fullStates) { - if (monitor.isCanceled()) { - return null; - } - if (quark >= fullState.size()) { - /* No information on this IRQ (yet?), skip it for now */ - continue; - } - ITmfStateInterval irqInterval = fullState.get(quark); - long time = irqInterval.getStartTime(); - long duration = irqInterval.getEndTime() - time + 1; - if (time == lastStartTime) { - continue; - } - if (!irqInterval.getStateValue().isNull()) { - int cpu = irqInterval.getStateValue().unboxInt(); - eventList.add(new TimeEvent(entry, time, duration, cpu)); - lastIsNull = false; - } else { - if (lastEndTime != time && lastIsNull) { - /* - * This is a special case where we want to show IRQ_ACTIVE - * state but we don't know the CPU (it is between two null - * samples) - */ - eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime, -1)); - } - if (isZoomThread) { - eventList.add(new NullTimeEvent(entry, time, duration)); - } - lastIsNull = true; - } - lastStartTime = time; - lastEndTime = time + duration; - } - return eventList; - } - - /** - * Signal handler for a cpu selected signal. - * - * @param signal - * the cpu selected signal - * @since 2.0 - */ - @TmfSignalHandler - public void listenToCpu(TmfCpuSelectedSignal signal) { - if (signal.getCore() >= 0) { - fCurrentCpu = signal.getCore(); - } else { - fCurrentCpu = -1; - } - } - -} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/AggregateEventIterator.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/AggregateEventIterator.java new file mode 100644 index 0000000000..0b631a4a75 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/AggregateEventIterator.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2016 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources; + +import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; + +/** + * Aggregate TimeEvent iterator, this takes multiple streams of events and + * merges them into one single time event stream + * + * @author Matthew Khouzam + * @since 2.0 + */ +public class AggregateEventIterator implements Iterator<@NonNull ITimeEvent> { + + private final List fIterators = new ArrayList<>(); + + private final Comparator fComparator; + + /** + * Constructor + * + * @param contributors + * the entries to aggregate + * @param comparator + * The comparator to sort time events + */ + public AggregateEventIterator(@NonNull List contributors, Comparator comparator) { + this(contributors, Long.MIN_VALUE, Long.MAX_VALUE, 1, comparator); + } + + /** + * Constructor with a time range + * + * @param contributors + * the entries to aggregate + * @param startTime + * start time in nanoseconds + * @param endTime + * stop time in nanoseconds + * @param duration + * duration of one pixel in nanoseconds + * @param comparator + * The comparator to sort time events + */ + public AggregateEventIterator(@NonNull List contributors, long startTime, long endTime, long duration, Comparator comparator) { + fComparator = comparator; + contributors.forEach(timeGraphEntry -> { + final Iterator<@NonNull ITimeEvent> timeEventsIterator = timeGraphEntry.getTimeEventsIterator(startTime, endTime, duration); + if (timeEventsIterator != null) { + CachingIterator iterator = new CachingIterator(timeEventsIterator, comparator); + if (iterator.hasNext()) { + fIterators.add(iterator); + } + } + }); + } + + @Override + public boolean hasNext() { + return !fIterators.isEmpty(); + } + + @Override + public @NonNull ITimeEvent next() { + + final List iterators = fIterators; + if (iterators.isEmpty()) { + throw new NoSuchElementException("Aggregate iterator is empty"); //$NON-NLS-1$ + } + + ITimeEvent winner = iterators.get(0).peek(); + long trimTime = winner.getTime() + winner.getDuration(); + for (int i = 1; i < iterators.size(); i++) { + CachingIterator iterator = iterators.get(i); + ITimeEvent candidate = iterator.peek(); + if (candidate.getTime() < winner.getTime()) { + trimTime = Math.min(winner.getTime(), candidate.getTime() + candidate.getDuration()); + winner = candidate; + } else if (candidate.getTime() == winner.getTime()) { + trimTime = Math.min(trimTime, candidate.getTime() + candidate.getDuration()); + if (fComparator.compare(candidate, winner) < 0) { + winner = candidate; + } + } else { + trimTime = Math.min(trimTime, candidate.getTime()); + } + } + + /* Trim the next event before the trim time, if necessary. */ + final ITimeEvent next = (trimTime < (winner.getDuration() + winner.getTime())) ? winner.splitBefore(trimTime) : winner; + + /* Trim all remaining events after the trim time, if necessary. */ + Iterator iteratorIterator = iterators.iterator(); + while (iteratorIterator.hasNext()) { + CachingIterator iterator = iteratorIterator.next(); + iterator.trim(trimTime); + /* Remove empty iterators from the list */ + if (!iterator.hasNext()) { + iteratorIterator.remove(); + } + } + + return checkNotNull(next); + } +} \ No newline at end of file diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/AggregateResourcesEntry.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/AggregateResourcesEntry.java new file mode 100644 index 0000000000..15ef08682b --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/AggregateResourcesEntry.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2016 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent; + +/** + * Internal entry of the aggregate kind, it is one without a state system value, + * it uses other entries and aggregates their values. + * + * @author Matthew Khouzam + */ +class AggregateResourcesEntry extends ResourcesEntry { + + private final @NonNull List fContributors = new ArrayList<>(); + + private static final Comparator COMPARATOR = new Comparator() { + @Override + public int compare(ITimeEvent o1, ITimeEvent o2) { + // largest value + return Integer.compare(getValue(o2), getValue(o1)); + } + + private int getValue(ITimeEvent element) { + return (element instanceof TimeEvent) ? ((TimeEvent) element).getValue() : Integer.MIN_VALUE; + } + }; + + /** + * AggregateResourcesEntry Constructor + * + * @param trace + * the parent trace + * @param startTime + * the start time + * @param endTime + * the end time + * @param type + * the type + * @param id + * the id + */ + public AggregateResourcesEntry(@NonNull ITmfTrace trace, + long startTime, long endTime, Type type, int id) { + super(ITmfStateSystem.INVALID_ATTRIBUTE, trace, startTime, endTime, type, id); + } + + /** + * Constructor + * + * @param trace + * The trace on which we are working + * @param name + * The exec_name of this entry + * @param startTime + * The start time of this entry lifetime + * @param endTime + * The end time of this entry + * @param type + * The type of this entry + * @param id + * The id of this entry + */ + public AggregateResourcesEntry(@NonNull ITmfTrace trace, String name, long startTime, long endTime, Type type, int id) { + super(ITmfStateSystem.INVALID_ATTRIBUTE, trace, name, startTime, endTime, type, id); + } + + @Override + public void addEvent(ITimeEvent event) { + } + + @Override + public void addZoomedEvent(ITimeEvent event) { + } + + @Override + public Iterator<@NonNull ITimeEvent> getTimeEventsIterator() { + return new AggregateEventIterator(fContributors, COMPARATOR); + } + + @Override + public Iterator<@NonNull ITimeEvent> getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) { + return new AggregateEventIterator(fContributors, startTime, stopTime, visibleDuration, COMPARATOR); + } + + public void addContributor(ITimeGraphEntry entry) { + fContributors.add(entry); + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/CachingIterator.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/CachingIterator.java new file mode 100644 index 0000000000..658ca5c4e2 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/CachingIterator.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2016 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources; + +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; + +/** + * Caching iterator of time events with a couple extras. + *
    + *
  • peek() allows reading the head without removing it
  • + *
  • trim() allows removing a bit of the first event
  • + *
+ * + * @author Matthew Khouzam + */ +class CachingIterator implements Iterator<@NonNull ITimeEvent>, Comparable { + private ITimeEvent fEvent; + private @NonNull Iterator<@NonNull ? extends ITimeEvent> fIterator; + private final Comparator fComparator; + + public CachingIterator(@NonNull Iterator<@NonNull ? extends ITimeEvent> iterator, Comparator comparator) { + fIterator = iterator; + fComparator = comparator; + fEvent = iterator.hasNext() ? iterator.next() : null; + } + + @Override + public ITimeEvent next() { + ITimeEvent retVal = fEvent; + fEvent = fIterator.hasNext() ? fIterator.next() : null; + if (retVal == null) { + throw new NoSuchElementException("Iterator is empty"); //$NON-NLS-1$ + } + return retVal; + } + + @Override + public boolean hasNext() { + return fEvent != null; + } + + /** + * Retrieves, but does not remove, the next element of this iterator, or + * returns {@code null} if this iterator does not have a next. + * + * @return the next element of the iterator + */ + public ITimeEvent peek() { + return fEvent; + } + + @Override + public int compareTo(CachingIterator o) { + final ITimeEvent myEvent = peek(); + final ITimeEvent otherEvent = o.peek(); + return fComparator.compare(myEvent, otherEvent); + } + + /** + * Trims the next element in the iterator to be after a cut-off time. + * + * @param time + * the cut-off time + * @return true if there was a trim + */ + public boolean trim(long time) { + if (time <= fEvent.getTime()) { + return false; + } + if (time < fEvent.getTime() + fEvent.getDuration()) { + fEvent = fEvent.splitAfter(time); + return true; + } + fEvent = fIterator.hasNext() ? fIterator.next() : null; + return true; + } + +} \ No newline at end of file diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesEntry.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesEntry.java new file mode 100644 index 0000000000..4b563552f6 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesEntry.java @@ -0,0 +1,194 @@ +/******************************************************************************* + * Copyright (c) 2012, 2015 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 + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Patrick Tasse - Initial API and implementation + * Geneviève Bastien - Move code to provide base classes for time graph view + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources; + +import java.util.Iterator; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry; + +/** + * An entry, or row, in the resource view + * + * @author Patrick Tasse + */ +public class ResourcesEntry extends TimeGraphEntry implements Comparable { + + /** Type of resource */ + public static enum Type { + /** Null resources (filler rows, etc.) */ + NULL, + /** Entries for CPUs */ + CPU, + /** Entries for IRQs */ + IRQ, + /** Entries for Soft IRQ */ + SOFT_IRQ + } + + private final int fId; + private final @NonNull ITmfTrace fTrace; + private final Type fType; + private final int fQuark; + + /** + * Constructor + * + * @param quark + * The attribute quark matching the entry + * @param trace + * The trace on which we are working + * @param name + * The exec_name of this entry + * @param startTime + * The start time of this entry lifetime + * @param endTime + * The end time of this entry + * @param type + * The type of this entry + * @param id + * The id of this entry + */ + public ResourcesEntry(int quark, @NonNull ITmfTrace trace, String name, + long startTime, long endTime, Type type, int id) { + super(name, startTime, endTime); + fId = id; + fTrace = trace; + fType = type; + fQuark = quark; + } + + /** + * Constructor + * + * @param trace + * The trace on which we are working + * @param name + * The exec_name of this entry + * @param startTime + * The start time of this entry lifetime + * @param endTime + * The end time of this entry + * @param id + * The id of this entry + */ + public ResourcesEntry(@NonNull ITmfTrace trace, String name, + long startTime, long endTime, int id) { + this(-1, trace, name, startTime, endTime, Type.NULL, id); + } + + /** + * Constructor + * + * @param quark + * The attribute quark matching the entry + * @param trace + * The trace on which we are working + * @param startTime + * The start time of this entry lifetime + * @param endTime + * The end time of this entry + * @param type + * The type of this entry + * @param id + * The id of this entry + */ + public ResourcesEntry(int quark, @NonNull ITmfTrace trace, + long startTime, long endTime, Type type, int id) { + this(quark, trace, computeEntryName(type, id), startTime, endTime, type, id); + } + + private static String computeEntryName(Type type, int id) { + if (Type.SOFT_IRQ.equals(type)) { + return type.toString() + ' ' + id + ' ' + SoftIrqLabelProvider.getSoftIrq(id); + } + return type.toString() + ' ' + id; + } + + /** + * Get the entry's id + * + * @return the entry's id + */ + public int getId() { + return fId; + } + + /** + * Get the entry's trace + * + * @return the entry's trace + */ + public @NonNull ITmfTrace getTrace() { + return fTrace; + } + + /** + * Get the entry Type of this entry. Uses the inner Type enum. + * + * @return The entry type + */ + public Type getType() { + return fType; + } + + /** + * Retrieve the attribute quark that's represented by this entry. + * + * @return The integer quark The attribute quark matching the entry + */ + public int getQuark() { + return fQuark; + } + + @Override + public boolean hasTimeEvents() { + if (fType == Type.NULL) { + return false; + } + return true; + } + + @Override + public int compareTo(ITimeGraphEntry other) { + if (!(other instanceof ResourcesEntry)) { + /* + * Should not happen, but if it does, put those entries at the end + */ + return -1; + } + ResourcesEntry o = (ResourcesEntry) other; + + /* + * Resources entry names should all be of type "ABC 123" + * + * We want to filter on the Type first (the "ABC" part), then on the ID + * ("123") in numerical order (so we get 1,2,10 and not 1,10,2). + */ + int ret = this.getType().compareTo(o.getType()); + if (ret != 0) { + return ret; + } + return Integer.compare(this.getId(), o.getId()); + } + + @Override + public Iterator<@NonNull ITimeEvent> getTimeEventsIterator() { + return super.getTimeEventsIterator(); + } + +} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesPresentationProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesPresentationProvider.java new file mode 100644 index 0000000000..2fb537db10 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesPresentationProvider.java @@ -0,0 +1,379 @@ +/******************************************************************************* + * Copyright (c) 2012, 2015 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 + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Patrick Tasse - Initial API and implementation + * Geneviève Bastien - Move code to provide base classes for time graph view + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule; +import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues; +import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout; +import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace; +import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.ResourcesEntry.Type; +import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; +import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; +import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; +import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException; +import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; +import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; +import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; +import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.StateItem; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.ITmfTimeGraphDrawingHelper; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.Resolution; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat; + +/** + * Presentation provider for the Resource view, based on the generic TMF + * presentation provider. + * + * @author Patrick Tasse + */ +public class ResourcesPresentationProvider extends TimeGraphPresentationProvider { + + private long fLastThreadId = -1; + private Color fColorWhite; + private Color fColorGray; + private Integer fAverageCharWidth; + + private enum State { + IDLE (new RGB(200, 200, 200)), + USERMODE (new RGB( 0, 200, 0)), + SYSCALL (new RGB( 0, 0, 200)), + IRQ (new RGB(200, 0, 100)), + SOFT_IRQ (new RGB(200, 150, 100)), + IRQ_ACTIVE (new RGB(200, 0, 100)), + SOFT_IRQ_RAISED (new RGB(200, 200, 0)), + SOFT_IRQ_ACTIVE (new RGB(200, 150, 100)); + + public final RGB rgb; + + private State(RGB rgb) { + this.rgb = rgb; + } + } + + /** + * Default constructor + */ + public ResourcesPresentationProvider() { + super(); + } + + private static State[] getStateValues() { + return State.values(); + } + + private static State getEventState(TimeEvent event) { + if (event.hasValue()) { + ResourcesEntry entry = (ResourcesEntry) event.getEntry(); + int value = event.getValue(); + + if (entry.getType() == Type.CPU) { + if (value == StateValues.CPU_STATUS_IDLE) { + return State.IDLE; + } else if (value == StateValues.CPU_STATUS_RUN_USERMODE) { + return State.USERMODE; + } else if (value == StateValues.CPU_STATUS_RUN_SYSCALL) { + return State.SYSCALL; + } else if (value == StateValues.CPU_STATUS_IRQ) { + return State.IRQ; + } else if (value == StateValues.CPU_STATUS_SOFTIRQ) { + return State.SOFT_IRQ; + } + } else if (entry.getType() == Type.IRQ) { + return State.IRQ_ACTIVE; + } else if (entry.getType() == Type.SOFT_IRQ) { + if (value == StateValues.CPU_STATUS_SOFT_IRQ_RAISED) { + return State.SOFT_IRQ_RAISED; + } + return State.SOFT_IRQ_ACTIVE; + } + } + return null; + } + + @Override + public int getStateTableIndex(ITimeEvent event) { + State state = getEventState((TimeEvent) event); + if (state != null) { + return state.ordinal(); + } + if (event instanceof NullTimeEvent) { + return INVISIBLE; + } + return TRANSPARENT; + } + + @Override + public StateItem[] getStateTable() { + State[] states = getStateValues(); + StateItem[] stateTable = new StateItem[states.length]; + for (int i = 0; i < stateTable.length; i++) { + State state = states[i]; + stateTable[i] = new StateItem(state.rgb, state.toString()); + } + return stateTable; + } + + @Override + public String getEventName(ITimeEvent event) { + State state = getEventState((TimeEvent) event); + if (state != null) { + return state.toString(); + } + if (event instanceof NullTimeEvent) { + return null; + } + return Messages.ResourcesView_multipleStates; + } + + @Override + public Map getEventHoverToolTipInfo(ITimeEvent event, long hoverTime) { + + Map retMap = new LinkedHashMap<>(); + if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) { + + TimeEvent tcEvent = (TimeEvent) event; + ResourcesEntry entry = (ResourcesEntry) event.getEntry(); + + if (tcEvent.hasValue()) { + ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID); + if (ss == null) { + return retMap; + } + // Check for IRQ or Soft_IRQ type + if (entry.getType().equals(Type.IRQ) || entry.getType().equals(Type.SOFT_IRQ)) { + + // Get CPU of IRQ or SoftIRQ and provide it for the tooltip display + int cpu = tcEvent.getValue(); + if (cpu >= 0) { + retMap.put(Messages.ResourcesView_attributeCpuName, String.valueOf(cpu)); + } + } + + // Check for type CPU + else if (entry.getType().equals(Type.CPU)) { + int status = tcEvent.getValue(); + + if (status == StateValues.CPU_STATUS_IRQ) { + // In IRQ state get the IRQ that caused the interruption + int cpu = entry.getId(); + + try { + List fullState = ss.queryFullState(event.getTime()); + List irqQuarks = ss.getQuarks(Attributes.CPUS, Integer.toString(cpu), Attributes.IRQS, "*"); //$NON-NLS-1$ + + for (int irqQuark : irqQuarks) { + if (fullState.get(irqQuark).getStateValue().unboxInt() == cpu) { + ITmfStateInterval value = ss.querySingleState(event.getTime(), irqQuark); + if (!value.getStateValue().isNull()) { + int irq = Integer.parseInt(ss.getAttributeName(irqQuark)); + retMap.put(Messages.ResourcesView_attributeIrqName, String.valueOf(irq)); + } + break; + } + } + } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) { + Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$ + } catch (StateSystemDisposedException e) { + /* Ignored */ + } + } else if (status == StateValues.CPU_STATUS_SOFTIRQ) { + // In SOFT_IRQ state get the SOFT_IRQ that caused the interruption + int cpu = entry.getId(); + + try { + List fullState = ss.queryFullState(event.getTime()); + List softIrqQuarks = ss.getQuarks(Attributes.CPUS, Integer.toString(cpu), Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$ + + for (int softIrqQuark : softIrqQuarks) { + if (fullState.get(softIrqQuark).getStateValue().unboxInt() == cpu) { + ITmfStateInterval value = ss.querySingleState(event.getTime(), softIrqQuark); + if (!value.getStateValue().isNull()) { + int softIrq = Integer.parseInt(ss.getAttributeName(softIrqQuark)); + retMap.put(Messages.ResourcesView_attributeSoftIrqName, String.valueOf(softIrq)); + } + break; + } + } + } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) { + Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$ + } catch (StateSystemDisposedException e) { + /* Ignored */ + } + } else if (status == StateValues.CPU_STATUS_RUN_USERMODE || status == StateValues.CPU_STATUS_RUN_SYSCALL) { + // In running state get the current tid + + try { + retMap.put(Messages.ResourcesView_attributeHoverTime, Utils.formatTime(hoverTime, TimeFormat.CALENDAR, Resolution.NANOSEC)); + int cpuQuark = entry.getQuark(); + int currentThreadQuark = ss.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD); + ITmfStateInterval interval = ss.querySingleState(hoverTime, currentThreadQuark); + if (!interval.getStateValue().isNull()) { + ITmfStateValue value = interval.getStateValue(); + int currentThreadId = value.unboxInt(); + retMap.put(Messages.ResourcesView_attributeTidName, Integer.toString(currentThreadId)); + int execNameQuark = ss.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.EXEC_NAME); + interval = ss.querySingleState(hoverTime, execNameQuark); + if (!interval.getStateValue().isNull()) { + value = interval.getStateValue(); + retMap.put(Messages.ResourcesView_attributeProcessName, value.unboxStr()); + } + if (status == StateValues.CPU_STATUS_RUN_SYSCALL) { + int syscallQuark = ss.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), Attributes.SYSTEM_CALL); + interval = ss.querySingleState(hoverTime, syscallQuark); + if (!interval.getStateValue().isNull()) { + value = interval.getStateValue(); + retMap.put(Messages.ResourcesView_attributeSyscallName, value.unboxStr()); + } + } + } + } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) { + Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$ + } catch (StateSystemDisposedException e) { + /* Ignored */ + } + } + } + } + } + + return retMap; + } + + @Override + public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) { + if (fColorGray == null) { + fColorGray = gc.getDevice().getSystemColor(SWT.COLOR_GRAY); + } + if (fColorWhite == null) { + fColorWhite = gc.getDevice().getSystemColor(SWT.COLOR_WHITE); + } + if (fAverageCharWidth == null) { + fAverageCharWidth = gc.getFontMetrics().getAverageCharWidth(); + } + + ITmfTimeGraphDrawingHelper drawingHelper = getDrawingHelper(); + if (bounds.width <= fAverageCharWidth) { + return; + } + + if (!(event instanceof TimeEvent)) { + return; + } + TimeEvent tcEvent = (TimeEvent) event; + if (!tcEvent.hasValue()) { + return; + } + + ResourcesEntry entry = (ResourcesEntry) event.getEntry(); + if (!entry.getType().equals(Type.CPU)) { + return; + } + + int status = tcEvent.getValue(); + if (status != StateValues.CPU_STATUS_RUN_USERMODE && status != StateValues.CPU_STATUS_RUN_SYSCALL) { + return; + } + + ITmfStateSystem ss = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), KernelAnalysisModule.ID); + if (ss == null) { + return; + } + long time = event.getTime(); + try { + while (time < event.getTime() + event.getDuration()) { + int cpuQuark = entry.getQuark(); + int currentThreadQuark = ss.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD); + ITmfStateInterval tidInterval = ss.querySingleState(time, currentThreadQuark); + long startTime = Math.max(tidInterval.getStartTime(), event.getTime()); + int x = Math.max(drawingHelper.getXForTime(startTime), bounds.x); + if (x >= bounds.x + bounds.width) { + break; + } + if (!tidInterval.getStateValue().isNull()) { + ITmfStateValue value = tidInterval.getStateValue(); + int currentThreadId = value.unboxInt(); + long endTime = Math.min(tidInterval.getEndTime() + 1, event.getTime() + event.getDuration()); + int xForEndTime = drawingHelper.getXForTime(endTime); + if (xForEndTime > bounds.x) { + int width = Math.min(xForEndTime, bounds.x + bounds.width) - x - 1; + if (width > 0) { + String attribute = null; + int beginIndex = 0; + if (status == StateValues.CPU_STATUS_RUN_USERMODE && currentThreadId != fLastThreadId) { + attribute = Attributes.EXEC_NAME; + } else if (status == StateValues.CPU_STATUS_RUN_SYSCALL) { + attribute = Attributes.SYSTEM_CALL; + /* + * Remove the "sys_" or "syscall_entry_" or similar from what we + * draw in the rectangle. This depends on the trace's event layout. + */ + ITmfTrace trace = entry.getTrace(); + if (trace instanceof IKernelTrace) { + IKernelAnalysisEventLayout layout = ((IKernelTrace) trace).getKernelEventLayout(); + beginIndex = layout.eventSyscallEntryPrefix().length(); + } + } + if (attribute != null) { + int quark = ss.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThreadId), attribute); + ITmfStateInterval interval = ss.querySingleState(time, quark); + if (!interval.getStateValue().isNull()) { + value = interval.getStateValue(); + gc.setForeground(fColorWhite); + int drawn = Utils.drawText(gc, value.unboxStr().substring(beginIndex), x + 1, bounds.y, width, bounds.height, true, true); + if (drawn > 0 && status == StateValues.CPU_STATUS_RUN_USERMODE) { + fLastThreadId = currentThreadId; + } + } + } + if (xForEndTime < bounds.x + bounds.width) { + gc.setForeground(fColorGray); + gc.drawLine(xForEndTime, bounds.y + 1, xForEndTime, bounds.y + bounds.height - 2); + } + } + } + } + // make sure next time is at least at the next pixel + time = Math.max(tidInterval.getEndTime() + 1, drawingHelper.getTimeAtX(x + 1)); + } + } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) { + Activator.getDefault().logError("Error in ResourcesPresentationProvider", e); //$NON-NLS-1$ + } catch (StateSystemDisposedException e) { + /* Ignored */ + } + } + + @Override + public void postDrawEntry(ITimeGraphEntry entry, Rectangle bounds, GC gc) { + fLastThreadId = -1; + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesView.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesView.java new file mode 100644 index 0000000000..b33a600637 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesView.java @@ -0,0 +1,450 @@ +/******************************************************************************* + * Copyright (c) 2012, 2016 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 + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Patrick Tasse - Initial API and implementation + * Geneviève Bastien - Move code to provide base classes for time graph views + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources; + +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.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule; +import org.eclipse.tracecompass.analysis.os.linux.core.signals.TmfCpuSelectedSignal; +import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.actions.FollowCpuAction; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.actions.UnfollowCpuAction; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.ResourcesEntry.Type; +import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; +import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; +import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; +import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; +import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractStateSystemTimeGraphView; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry; + +/** + * Main implementation for the LTTng 2.0 kernel Resource view + * + * @author Patrick Tasse + */ +public class ResourcesView extends AbstractStateSystemTimeGraphView { + + /** View ID. */ + public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.resources"; //$NON-NLS-1$ + + private static final String[] FILTER_COLUMN_NAMES = new String[] { + Messages.ResourcesView_stateTypeName + }; + + private int fCurrentCpu = -1; + + // Timeout between updates in the build thread in ms + private static final long BUILD_UPDATE_TIMEOUT = 500; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * Default constructor + */ + public ResourcesView() { + super(ID, new ResourcesPresentationProvider()); + setFilterColumns(FILTER_COLUMN_NAMES); + setFilterLabelProvider(new ResourcesFilterLabelProvider()); + setEntryComparator(new ResourcesEntryComparator()); + setAutoExpandLevel(1); + } + + private static class ResourcesEntryComparator implements Comparator { + @Override + public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) { + ResourcesEntry entry1 = (ResourcesEntry) o1; + ResourcesEntry entry2 = (ResourcesEntry) o2; + if (entry1.getType() == Type.NULL && entry2.getType() == Type.NULL) { + /* sort trace entries alphabetically */ + return entry1.getName().compareTo(entry2.getName()); + } + /* sort resource entries by their defined order */ + return entry1.compareTo(entry2); + } + } + + + /** + * @since 2.0 + */ + @Override + protected void fillTimeGraphEntryContextMenu(@NonNull IMenuManager menuManager) { + ISelection selection = getSite().getSelectionProvider().getSelection(); + if (selection instanceof IStructuredSelection) { + IStructuredSelection sSel = (IStructuredSelection) selection; + if (sSel.getFirstElement() instanceof ResourcesEntry) { + ResourcesEntry resourcesEntry = (ResourcesEntry) sSel.getFirstElement(); + if (resourcesEntry.getType().equals(ResourcesEntry.Type.CPU)) { + if (fCurrentCpu >= 0) { + menuManager.add(new UnfollowCpuAction(ResourcesView.this, resourcesEntry.getId(), resourcesEntry.getTrace())); + } else { + menuManager.add(new FollowCpuAction(ResourcesView.this, resourcesEntry.getId(), resourcesEntry.getTrace())); + } + } + } + } + } + + private static class ResourcesFilterLabelProvider extends TreeLabelProvider { + @Override + public String getColumnText(Object element, int columnIndex) { + ResourcesEntry entry = (ResourcesEntry) element; + if (columnIndex == 0) { + return entry.getName(); + } + return ""; //$NON-NLS-1$ + } + + } + + // ------------------------------------------------------------------------ + // Internal + // ------------------------------------------------------------------------ + + @Override + protected String getNextText() { + return Messages.ResourcesView_nextResourceActionNameText; + } + + @Override + protected String getNextTooltip() { + return Messages.ResourcesView_nextResourceActionToolTipText; + } + + @Override + protected String getPrevText() { + return Messages.ResourcesView_previousResourceActionNameText; + } + + @Override + protected String getPrevTooltip() { + return Messages.ResourcesView_previousResourceActionToolTipText; + } + + @Override + protected void buildEntryList(ITmfTrace trace, ITmfTrace parentTrace, final IProgressMonitor monitor) { + final ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysisModule.ID); + if (ssq == null) { + return; + } + + 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; + } + 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, ssq, entryList); + } else { + traceEntry.updateEndTime(endTime); + } + List cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$ + createCpuEntriesWithQuark(trace, ssq, entryMap, traceEntry, startTime, endTime, cpuQuarks); + if (parentTrace.equals(getTrace())) { + refresh(); + } + final List<@NonNull TimeGraphEntry> traceEntryChildren = traceEntry.getChildren(); + final long resolution = Math.max(1, (endTime - ssq.getStartTime()) / getDisplayWidth()); + queryFullStates(ssq, ssq.getStartTime(), end, resolution, monitor, new IQueryHandler() { + @Override + public void handle(List> fullStates, List prevFullState) { + for (TimeGraphEntry child : traceEntryChildren) { + if (!populateEventsRecursively(fullStates, prevFullState, child).isOK()) { + return; + } + } + } + + private IStatus populateEventsRecursively(@NonNull List> fullStates, @Nullable List prevFullState, @NonNull TimeGraphEntry entry) { + if (monitor.isCanceled()) { + return Status.CANCEL_STATUS; + } + List eventList = getEventList(entry, ssq, fullStates, prevFullState, monitor); + if (eventList != null) { + /* Start a new event list on first iteration, then append to it */ + if (prevFullState == null) { + entry.setEventList(eventList); + } else { + for (ITimeEvent event : eventList) { + entry.addEvent(event); + } + } + } + for (TimeGraphEntry child : entry.getChildren()) { + IStatus status = populateEventsRecursively(fullStates, prevFullState, child); + if (!status.isOK()) { + return status; + } + } + return Status.OK_STATUS; + } + }); + + start = end; + } + + } + + private static void createCpuEntriesWithQuark(@NonNull ITmfTrace trace, final ITmfStateSystem ssq, Map entryMap, TimeGraphEntry traceEntry, long startTime, long endTime, List cpuQuarks) { + for (Integer cpuQuark : cpuQuarks) { + final @NonNull String cpuName = ssq.getAttributeName(cpuQuark); + int cpu = Integer.parseInt(cpuName); + ResourcesEntry cpuEntry = entryMap.get(cpuQuark); + if (cpuEntry == null) { + cpuEntry = new ResourcesEntry(cpuQuark, trace, startTime, endTime, Type.CPU, cpu); + entryMap.put(cpuQuark, cpuEntry); + traceEntry.addChild(cpuEntry); + } else { + cpuEntry.updateEndTime(endTime); + } + List irqQuarks = ssq.getQuarks(Attributes.CPUS, cpuName, Attributes.IRQS, "*"); //$NON-NLS-1$ + createCpuInterruptEntryWithQuark(trace, ssq, entryMap, startTime, endTime, traceEntry, cpuEntry, irqQuarks, Type.IRQ); + List softIrqQuarks = ssq.getQuarks(Attributes.CPUS, cpuName, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$ + createCpuInterruptEntryWithQuark(trace, ssq, entryMap, startTime, endTime, traceEntry, cpuEntry, softIrqQuarks, Type.SOFT_IRQ); + } + } + + /** + * Create and add execution contexts to a cpu entry. Also creates an + * aggregate entry in the root trace entry. The execution context is + * basically what the cpu is doing in its execution stack. It can be in an + * IRQ, Soft IRQ. MCEs, NMIs, Userland and Kernel execution is not yet + * supported. + * + * @param trace + * the trace + * @param ssq + * the state system + * @param entryMap + * the entry map + * @param startTime + * the start time in nanoseconds + * @param endTime + * the end time in nanoseconds + * @param traceEntry + * the trace timegraph entry + * @param cpuEntry + * the cpu timegraph entry (the entry under the trace entry + * @param childrenQuarks + * the quarks to add to cpu entry + * @param type + * the type of entry being added + */ + private static void createCpuInterruptEntryWithQuark(@NonNull ITmfTrace trace, + final ITmfStateSystem ssq, Map entryMap, + long startTime, long endTime, + TimeGraphEntry traceEntry, ResourcesEntry cpuEntry, + List childrenQuarks, Type type) { + for (Integer quark : childrenQuarks) { + final @NonNull String resourceName = ssq.getAttributeName(quark); + int resourceId = Integer.parseInt(resourceName); + ResourcesEntry interruptEntry = entryMap.get(quark); + if (interruptEntry == null) { + interruptEntry = new ResourcesEntry(quark, trace, startTime, endTime, type, resourceId); + entryMap.put(quark, interruptEntry); + cpuEntry.addChild(interruptEntry); + boolean found = false; + for (ITimeGraphEntry rootElem : traceEntry.getChildren()) { + if (rootElem instanceof AggregateResourcesEntry) { + AggregateResourcesEntry aggregateInterruptEntry = (AggregateResourcesEntry) rootElem; + if (aggregateInterruptEntry.getId() == resourceId && aggregateInterruptEntry.getType().equals(type)) { + found = true; + aggregateInterruptEntry.addContributor(interruptEntry); + final AggregateResourcesEntry irqCpuEntry = new AggregateResourcesEntry(trace, cpuEntry.getName(), startTime, endTime, type, cpuEntry.getId()); + irqCpuEntry.addContributor(interruptEntry); + aggregateInterruptEntry.addChild(irqCpuEntry); + break; + } + } + } + if (!found) { + AggregateResourcesEntry aggregateInterruptEntry = new AggregateResourcesEntry(trace, startTime, endTime, type, resourceId); + aggregateInterruptEntry.addContributor(interruptEntry); + final AggregateResourcesEntry irqCpuEntry = new AggregateResourcesEntry(trace, cpuEntry.getName(), startTime, endTime, type, cpuEntry.getId()); + irqCpuEntry.addContributor(interruptEntry); + aggregateInterruptEntry.addChild(irqCpuEntry); + traceEntry.addChild(aggregateInterruptEntry); + } + } else { + interruptEntry.updateEndTime(endTime); + } + } + } + + @Override + protected @Nullable List getEventList(@NonNull TimeGraphEntry entry, ITmfStateSystem ssq, + @NonNull List> fullStates, @Nullable List prevFullState, @NonNull IProgressMonitor monitor) { + ResourcesEntry resourcesEntry = (ResourcesEntry) entry; + int quark = resourcesEntry.getQuark(); + + if (resourcesEntry.getType().equals(Type.CPU)) { + return createCpuEventsList(entry, ssq, fullStates, prevFullState, monitor, quark); + } else if ((resourcesEntry.getType().equals(Type.IRQ) || resourcesEntry.getType().equals(Type.SOFT_IRQ)) && (quark >= 0)) { + return createIrqEventsList(entry, fullStates, prevFullState, monitor, quark); + } + + return null; + } + + private static List createCpuEventsList(ITimeGraphEntry entry, ITmfStateSystem ssq, List> fullStates, List prevFullState, IProgressMonitor monitor, int quark) { + List eventList; + int statusQuark; + try { + statusQuark = ssq.getQuarkRelative(quark, Attributes.STATUS); + } catch (AttributeNotFoundException e) { + /* + * The sub-attribute "status" is not available. May happen if the + * trace does not have sched_switch events enabled. + */ + return null; + } + boolean isZoomThread = Thread.currentThread() instanceof ZoomThread; + eventList = new ArrayList<>(fullStates.size()); + ITmfStateInterval lastInterval = prevFullState == null || statusQuark >= prevFullState.size() ? null : prevFullState.get(statusQuark); + long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime(); + long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1; + for (List fullState : fullStates) { + if (monitor.isCanceled()) { + return null; + } + if (statusQuark >= fullState.size()) { + /* No information on this CPU (yet?), skip it for now */ + continue; + } + ITmfStateInterval statusInterval = fullState.get(statusQuark); + int status = statusInterval.getStateValue().unboxInt(); + long time = statusInterval.getStartTime(); + long duration = statusInterval.getEndTime() - time + 1; + if (time == lastStartTime) { + continue; + } + if (!statusInterval.getStateValue().isNull()) { + if (lastEndTime != time && lastEndTime != -1) { + eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime)); + } + eventList.add(new TimeEvent(entry, time, duration, status)); + } else if (isZoomThread) { + eventList.add(new NullTimeEvent(entry, time, duration)); + } + lastStartTime = time; + lastEndTime = time + duration; + } + return eventList; + } + + private static List createIrqEventsList(ITimeGraphEntry entry, List> fullStates, List prevFullState, IProgressMonitor monitor, int quark) { + List eventList; + boolean isZoomThread = Thread.currentThread() instanceof ZoomThread; + eventList = new ArrayList<>(fullStates.size()); + ITmfStateInterval lastInterval = prevFullState == null || quark >= prevFullState.size() ? null : prevFullState.get(quark); + long lastStartTime = lastInterval == null ? -1 : lastInterval.getStartTime(); + long lastEndTime = lastInterval == null ? -1 : lastInterval.getEndTime() + 1; + boolean lastIsNull = lastInterval == null ? false : lastInterval.getStateValue().isNull(); + for (List fullState : fullStates) { + if (monitor.isCanceled()) { + return null; + } + if (quark >= fullState.size()) { + /* No information on this IRQ (yet?), skip it for now */ + continue; + } + ITmfStateInterval irqInterval = fullState.get(quark); + long time = irqInterval.getStartTime(); + long duration = irqInterval.getEndTime() - time + 1; + if (time == lastStartTime) { + continue; + } + if (!irqInterval.getStateValue().isNull()) { + int cpu = irqInterval.getStateValue().unboxInt(); + eventList.add(new TimeEvent(entry, time, duration, cpu)); + lastIsNull = false; + } else { + if (lastEndTime != time && lastIsNull) { + /* + * This is a special case where we want to show IRQ_ACTIVE + * state but we don't know the CPU (it is between two null + * samples) + */ + eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime, -1)); + } + if (isZoomThread) { + eventList.add(new NullTimeEvent(entry, time, duration)); + } + lastIsNull = true; + } + lastStartTime = time; + lastEndTime = time + duration; + } + return eventList; + } + + /** + * Signal handler for a cpu selected signal. + * + * @param signal + * the cpu selected signal + * @since 2.0 + */ + @TmfSignalHandler + public void listenToCpu(TmfCpuSelectedSignal signal) { + if (signal.getCore() >= 0) { + fCurrentCpu = signal.getCore(); + } else { + fCurrentCpu = -1; + } + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ImportAndReadKernelSmokeTest.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ImportAndReadKernelSmokeTest.java index ad9cb896f9..b9858daca6 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ImportAndReadKernelSmokeTest.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ImportAndReadKernelSmokeTest.java @@ -28,7 +28,7 @@ import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; import org.eclipse.swtbot.swt.finder.results.VoidResult; import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarButton; import org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow.ControlFlowView; -import org.eclipse.tracecompass.analysis.os.linux.ui.views.resources.ResourcesView; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.ResourcesView; import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal; import org.eclipse.tracecompass.tmf.core.trace.ITmfContext; diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelPerspectiveChecker.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelPerspectiveChecker.java index 192c1b98c4..82fba6fb19 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelPerspectiveChecker.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelPerspectiveChecker.java @@ -16,7 +16,7 @@ import java.util.ArrayList; import java.util.Arrays; import org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow.ControlFlowView; -import org.eclipse.tracecompass.analysis.os.linux.ui.views.resources.ResourcesView; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.ResourcesView; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.ControlView; import org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.PerspectiveFactory; import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.AbstractPerspectiveChecker; diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/PerspectiveFactory.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/PerspectiveFactory.java index 92688afd70..934920cc5b 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/PerspectiveFactory.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui/src/org/eclipse/tracecompass/internal/lttng2/kernel/ui/views/PerspectiveFactory.java @@ -13,7 +13,7 @@ package org.eclipse.tracecompass.internal.lttng2.kernel.ui.views; import org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow.ControlFlowView; -import org.eclipse.tracecompass.analysis.os.linux.ui.views.resources.ResourcesView; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.ResourcesView; import org.eclipse.tracecompass.internal.lttng2.control.ui.views.ControlView; import org.eclipse.tracecompass.tmf.ui.project.wizards.NewTmfProjectWizard; import org.eclipse.tracecompass.tmf.ui.views.histogram.HistogramView;