linux: introduce execution contexts in resources view
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Mon, 1 Feb 2016 21:51:15 +0000 (16:51 -0500)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Thu, 3 Mar 2016 21:19:25 +0000 (16:19 -0500)
The original implementation made sense only one single core systems. An
IRQ and softirq would block the whole system and not just a single core.

This patch adds the notion of execution contexts to the interrupts. The
interrupts are moved under the CPU to show the true execution stack.
Then the model is a much truer representation of the kernel.

In order to maintain aggregate information in the resources view (total
IRQs and such), the notion of AggregateEntries and AggregateIterators
are introduced.

This allows better understanding of the current state of the system as
the resources view now shows what the state of each processor is.

Expect a _SLIGHT_ performance degradation during the building of the
state system as an additional lookup is required for each interrupt
event.

This updates the state system model so the testvalues are updated and
the generator is updated to work again.

Starts to fix bugs: bug 381497 and bug 481855

Change-Id: I2f0f2093344f51caaf08500181cf90400a081f7c
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-on: https://git.eclipse.org/r/65609
Reviewed-by: Hudson CI
17 files changed:
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernelanalysis/Attributes.java
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/KernelStateProvider.java
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IrqEntryHandler.java
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/IrqExitHandler.java
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/KernelEventHandlerUtils.java
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqEntryHandler.java
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqExitHandler.java
analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/internal/analysis/os/linux/core/kernel/handlers/SoftIrqRaiseHandler.java
analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/resources/AggregateIteratorTest.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateEventIterator.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateResourcesEntry.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/CachingIterator.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesPresentationProvider.java
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/ResourcesView.java
lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/GenerateTestValues.java
lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/StateSystemTest.java
lttng/org.eclipse.tracecompass.lttng2.kernel.core.tests/src/org/eclipse/tracecompass/lttng2/kernel/core/tests/analysis/kernel/statesystem/TestValues.java

index 520b1bb2d0a92a7334d71d5268b2aa18f4b05158..3324ea9e59cfdb7712d2be37357fc3aaec910796 100644 (file)
@@ -30,11 +30,12 @@ public interface Attributes {
     /* First-level attributes */
     String CPUS = "CPUs";
     String THREADS = "Threads";
-    String RESOURCES = "Resources";
 
     /* Sub-attributes of the CPU nodes */
     String CURRENT_THREAD = "Current_thread";
     String STATUS = "Status";
+    String SOFT_IRQS = "Soft_IRQs";
+    String IRQS = "IRQs";
 
     /* Sub-attributes of the Thread nodes */
     String PPID = "PPID";
@@ -45,10 +46,6 @@ public interface Attributes {
     String PRIO = "Prio";
     String SYSTEM_CALL = "System_call";
 
-    /* Attributes under "Resources" */
-    String IRQS = "IRQs";
-    String SOFT_IRQS = "Soft_IRQs";
-
     /* Misc stuff */
     String UNKNOWN = "Unknown";
 }
index 279e0db21c8ea9b77386c61dec2500a884787d97..3783768660897a26430e215346611236cf04bb37 100644 (file)
@@ -44,10 +44,8 @@ import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import com.google.common.collect.ImmutableMap;
 
 /**
- * This is the state change input plugin for TMF's state system which handles
- * the LTTng 2.0 kernel traces in CTF format.
- *
- * It uses the reference handler defined in CTFKernelHandler.java.
+ * This is the state change input plugin for the state system which handles the
+ * kernel traces.
  *
  * @author Alexandre Montplaisir
  */
@@ -61,7 +59,7 @@ public class KernelStateProvider extends AbstractTmfStateProvider {
      * Version number of this state provider. Please bump this if you modify the
      * contents of the generated state history in some way.
      */
-    private static final int VERSION = 11;
+    private static final int VERSION = 12;
 
     // ------------------------------------------------------------------------
     // Fields
index d1897b7cd2ef4cda9cca0d5dc17d004e1252215c..bcc6fa04598b105679f99f851bf1936b2df11f5f 100644 (file)
@@ -49,7 +49,7 @@ public class IrqEntryHandler extends KernelEventHandler {
          * Mark this IRQ as active in the resource tree. The state value = the
          * CPU on which this IRQ is sitting
          */
-        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeIRQs(ss), irqId.toString());
+        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeIRQs(cpu, ss), irqId.toString());
 
         ITmfStateValue value = TmfStateValue.newValueInt(cpu.intValue());
         long timestamp = KernelEventHandlerUtils.getTimestamp(event);
index 81e7f024a7532fe345c2404fdbd64989010d6356..9b2103e2bc2d5cf2de9867d2d4c38dfe226ec722 100644 (file)
@@ -36,13 +36,13 @@ public class IrqExitHandler extends KernelEventHandler {
     @Override
     public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
         Integer cpu = KernelEventHandlerUtils.getCpu(event);
-        if( cpu == null ) {
+        if (cpu == null) {
             return;
         }
         int currentThreadNode = KernelEventHandlerUtils.getCurrentThreadNode(cpu, ss);
         Integer irqId = ((Long) event.getContent().getField(getLayout().fieldIrq()).getValue()).intValue();
         /* Put this IRQ back to inactive in the resource tree */
-        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeIRQs(ss), irqId.toString());
+        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeIRQs(cpu, ss), irqId.toString());
         TmfStateValue value = TmfStateValue.nullValue();
         long timestamp = KernelEventHandlerUtils.getTimestamp(event);
         ss.modifyAttribute(timestamp, value, quark);
index a6ab3f5d4b256888f7d8302e0ab737d46f8fc45a..fad83ac0c444e00f9825a589346d2c0b7a25e6c2 100644 (file)
@@ -30,7 +30,8 @@ import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
  */
 public final class KernelEventHandlerUtils {
 
-    private KernelEventHandlerUtils() {}
+    private KernelEventHandlerUtils() {
+    }
 
     /**
      * Get CPU
@@ -63,7 +64,6 @@ public final class KernelEventHandlerUtils {
         return ss.getQuarkRelativeAndAdd(getNodeCPUs(ss), cpuNumber.toString());
     }
 
-
     /**
      * Get the timestamp of the event
      *
@@ -139,12 +139,14 @@ public final class KernelEventHandlerUtils {
     /**
      * Get the IRQs node
      *
+     * @param cpuNumber
+     *            the cpu core
      * @param ss
      *            the state system
      * @return the IRQ node quark
      */
-    public static int getNodeIRQs(ITmfStateSystemBuilder ss) {
-        return ss.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.IRQS);
+    public static int getNodeIRQs(int cpuNumber, ITmfStateSystemBuilder ss) {
+        return ss.getQuarkAbsoluteAndAdd(Attributes.CPUS, Integer.toString(cpuNumber), Attributes.IRQS);
     }
 
     /**
@@ -161,12 +163,14 @@ public final class KernelEventHandlerUtils {
     /**
      * Get the Soft IRQs node
      *
+     * @param cpuNumber
+     *            the cpu core
      * @param ss
      *            the state system
      * @return the Soft IRQ node quark
      */
-    public static int getNodeSoftIRQs(ITmfStateSystemBuilder ss) {
-        return ss.getQuarkAbsoluteAndAdd(Attributes.RESOURCES, Attributes.SOFT_IRQS);
+    public static int getNodeSoftIRQs(int cpuNumber, ITmfStateSystemBuilder ss) {
+        return ss.getQuarkAbsoluteAndAdd(Attributes.CPUS, Integer.toString(cpuNumber), Attributes.SOFT_IRQS);
     }
 
     /**
index 60dd3c21684a9589b72d7412c772ad20d963562e..39e08ef416510c6ea953514829928b0e460f55a0 100644 (file)
@@ -52,7 +52,7 @@ public class SoftIrqEntryHandler extends KernelEventHandler {
          * Mark this SoftIRQ as active in the resource tree. The state value =
          * the CPU on which this SoftIRQ is processed
          */
-        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(ss), softIrqId.toString());
+        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(cpu, ss), softIrqId.toString());
         ITmfStateValue value = TmfStateValue.newValueInt(cpu.intValue());
         ss.modifyAttribute(timestamp, value, quark);
 
index f348b020765d545c02614c3aa634bfcd4d3a1947..110fe4d570d328cfde30075d8df93bcbf6e17ef9 100644 (file)
@@ -44,7 +44,7 @@ public class SoftIrqExitHandler extends KernelEventHandler {
         Integer softIrqId = ((Long) event.getContent().getField(getLayout().fieldVec()).getValue()).intValue();
         int currentThreadNode = KernelEventHandlerUtils.getCurrentThreadNode(cpu, ss);
         /* Put this SoftIRQ back to inactive (= -1) in the resource tree */
-        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(ss), softIrqId.toString());
+        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(cpu, ss), softIrqId.toString());
         ITmfStateValue value = TmfStateValue.nullValue();
         long timestamp = KernelEventHandlerUtils.getTimestamp(event);
 
index 3813ca0efc9ac8e7a693d2c3d04ef29da9c768bf..6773c6491fe46a19cd40cf15741caacfb63ab4fb 100644 (file)
@@ -26,7 +26,9 @@ public class SoftIrqRaiseHandler extends KernelEventHandler {
 
     /**
      * Constructor
-     * @param layout event layout
+     *
+     * @param layout
+     *            event layout
      */
     public SoftIrqRaiseHandler(IKernelAnalysisEventLayout layout) {
         super(layout);
@@ -35,11 +37,14 @@ public class SoftIrqRaiseHandler extends KernelEventHandler {
     @Override
     public void handleEvent(ITmfStateSystemBuilder ss, ITmfEvent event) throws AttributeNotFoundException {
         Integer softIrqId = ((Long) event.getContent().getField(getLayout().fieldVec()).getValue()).intValue();
-
+        Integer cpu = KernelEventHandlerUtils.getCpu(event);
+        if (cpu == null) {
+            return;
+        }
         /*
          * Mark this SoftIRQ as *raised* in the resource tree. State value = -2
          */
-        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(ss), softIrqId.toString());
+        int quark = ss.getQuarkRelativeAndAdd(KernelEventHandlerUtils.getNodeSoftIRQs(cpu, ss), softIrqId.toString());
         ITmfStateValue value = StateValues.SOFT_IRQ_RAISED_VALUE;
         ss.modifyAttribute(KernelEventHandlerUtils.getTimestamp(event), value, quark);
     }
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
new file mode 100644 (file)
index 0000000..97b0ef0
--- /dev/null
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * 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.tests.view.resources;
+
+import static org.junit.Assert.assertEquals;
+
+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.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.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;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+
+/**
+ * Test class to verify the main cases of the aggregate iterator
+ *
+ * @author Matthew Khouzam
+ *
+ */
+@NonNullByDefault
+public class AggregateIteratorTest {
+
+    /**
+     * <pre>
+     * ----------X---------
+     * </pre>
+     */
+    private final ITimeGraphEntry t1 = new StubTimeGraphEntry(ImmutableList.of(
+            new NullTimeEvent(null, 0, 10),
+            new TimeEvent(null, 10, 1, 1),
+            new NullTimeEvent(null, 11, 9)));
+    /**
+     * <pre>
+     * -----------X--------
+     * </pre>
+     */
+    private final ITimeGraphEntry t2 = new StubTimeGraphEntry(ImmutableList.of(
+            new NullTimeEvent(null, 0, 12),
+            new TimeEvent(null, 12, 1, 1),
+            new NullTimeEvent(null, 13, 7)));
+    /**
+     * <pre>
+     * --------X-----------
+     * </pre>
+     */
+    private final ITimeGraphEntry t3 = new StubTimeGraphEntry(ImmutableList.of(
+            new NullTimeEvent(null, 0, 9),
+            new TimeEvent(null, 9, 1, 1),
+            new NullTimeEvent(null, 10, 10)));
+
+    /**
+     * <pre>
+     * --------XXX---------
+     * </pre>
+     */
+    private final ITimeGraphEntry t4 = new StubTimeGraphEntry(ImmutableList.of(
+            new NullTimeEvent(null, 0, 9),
+            new TimeEvent(null, 9, 3, 1),
+            new NullTimeEvent(null, 12, 8)));
+
+    /**
+     * <pre>
+     * ----------XXX-------
+     * </pre>
+     */
+    private final ITimeGraphEntry t5 = new StubTimeGraphEntry(ImmutableList.of(
+            new NullTimeEvent(null, 0, 10),
+            new TimeEvent(null, 10, 3, 1),
+            new NullTimeEvent(null, 13, 7)));
+
+    /**
+     * <pre>
+     * ----------XXX-------
+     * </pre>
+     */
+    private final ITimeGraphEntry t6 = new StubTimeGraphEntry(ImmutableList.of(
+            new NullTimeEvent(null, 0, 10),
+            new TimeEvent(null, 10, 3, 1),
+            new NullTimeEvent(null, 13, 7)));
+
+    /**
+     * <pre>
+     * XXXXXXXXXXXXXXXXXXXX
+     * </pre>
+     */
+    private final ITimeGraphEntry t7 = new StubTimeGraphEntry(ImmutableList.of(
+            new TimeEvent(null, 0, 20, 1)));
+
+    /**
+     * Test non-overlapping intervals
+     */
+    @Test
+    public void testNoOverlap() {
+        List<ITimeEvent> expected = ImmutableList.of(new NullTimeEvent(null, 0, 9), new TimeEvent(null, 9, 1, 1), new TimeEvent(null, 10, 1, 1), new NullTimeEvent(null, 11, 1), new TimeEvent(null, 12, 1, 1), new NullTimeEvent(null, 13, 7));
+        AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t1, t2, t3), COMPARATOR);
+        runTest(expected, fixture);
+    }
+
+    /**
+     * Test intervals with 2 events that partially overlap
+     */
+    @Test
+    public void testPartialOverlap() {
+        List<ITimeEvent> expected = ImmutableList.of(new NullTimeEvent(null, 0, 9), new TimeEvent(null, 9, 1, 1), new TimeEvent(null, 10, 2, 1), new TimeEvent(null, 12, 1, 1), new NullTimeEvent(null, 13, 7));
+        AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t4, t5), COMPARATOR);
+        runTest(expected, fixture);
+    }
+
+    /**
+     * Test two iterators that are identical, it will give the same result
+     */
+    @Test
+    public void testFullOverlap() {
+        List<ITimeEvent> expected = ImmutableList.of(new NullTimeEvent(null, 0, 10), new TimeEvent(null, 10, 3, 1), new NullTimeEvent(null, 13, 7));
+        AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t6, t5), COMPARATOR);
+        runTest(expected, fixture);
+    }
+
+    /**
+     * Test two iterators that are identical, it will give the same result
+     */
+    @Test
+    public void testSameStartOverlap() {
+        List<ITimeEvent> expected = ImmutableList.of(new NullTimeEvent(null, 0, 9), new TimeEvent(null, 9, 1, 1), new TimeEvent(null, 10, 2, 1), new NullTimeEvent(null, 12, 8));
+        AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t3, t4), COMPARATOR);
+        runTest(expected, fixture);
+    }
+
+    /**
+     * Test two iterators that are identical, it will give the same result
+     */
+    @Test
+    public void testSameEndOverlap() {
+        List<ITimeEvent> expected = ImmutableList.of(new NullTimeEvent(null, 0, 10), new TimeEvent(null, 10, 2, 1), new TimeEvent(null, 12, 1, 1), new NullTimeEvent(null, 13, 7));
+        AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t5, t2), COMPARATOR);
+        runTest(expected, fixture);
+    }
+
+    /**
+     * Test two iterators where one only has one HUGE event
+     */
+    @Test
+    public void testOverlapEnglobing() {
+        List<ITimeEvent> expected = ImmutableList.of(new TimeEvent(null, 0, 10, 1), new TimeEvent(null, 10, 1, 1), new TimeEvent(null, 11, 9, 1));
+        AggregateEventIterator fixture = new AggregateEventIterator(ImmutableList.of(t1, t7), COMPARATOR);
+        runTest(expected, fixture);
+    }
+
+    private static void runTest(List<ITimeEvent> expected, AggregateEventIterator fixture) {
+        List<ITimeEvent> results = new ArrayList<>();
+        Iterators.addAll(results, fixture);
+        assertEquals(expected.size(), results.size());
+        for (int i = 0; i < expected.size(); i++) {
+            final @NonNull TimeEvent actual = (@NonNull TimeEvent) results.get(i);
+            final @NonNull TimeEvent expected2 = (@NonNull TimeEvent) expected.get(i);
+            final @NonNull String name = Integer.toString(i);
+            assertEquals(name, expected2.getClass(), actual.getClass());
+            assertEquals(name, expected2.getDuration(), actual.getDuration());
+            assertEquals(name, expected2.getTime(), actual.getTime());
+            assertEquals(name, expected2.getEntry(), actual.getEntry());
+            assertEquals(name, expected2.getValue(), actual.getValue());
+        }
+    }
+
+    static class StubTimeGraphEntry extends TimeGraphEntry {
+
+        private final Iterable<@NonNull ITimeEvent> fEvents;
+
+        public StubTimeGraphEntry(Iterable<ITimeEvent> events) {
+            super("stub", Long.MIN_VALUE, Long.MAX_VALUE);
+            fEvents = events;
+        }
+
+        @Override
+        public boolean hasTimeEvents() {
+            return !Iterables.isEmpty(fEvents);
+        }
+
+        // for a stub, not worth making it work.
+        @SuppressWarnings("null")
+        @Override
+        public Iterator<@NonNull ITimeEvent> getTimeEventsIterator() {
+            return fEvents.iterator();
+        }
+
+        @Override
+        public Iterator<@NonNull ITimeEvent> getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) {
+            if (startTime != Long.MIN_VALUE || stopTime != Long.MAX_VALUE) {
+                throw new IllegalArgumentException("startTime must be Long.MIN_VALUE, stopTime must be Long.MAX_VALUE");
+            }
+            return getTimeEventsIterator();
+        }
+
+    }
+
+    /**
+     * Same as in AggregateResourcesEntry but we want a snapshot and to not
+     * update the tests at every new mode of resources view
+     */
+    private static final Comparator<ITimeEvent> COMPARATOR = new Comparator<ITimeEvent>() {
+        @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;
+        }
+    };
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateEventIterator.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/resources/AggregateEventIterator.java
new file mode 100644 (file)
index 0000000..6ecb4f9
--- /dev/null
@@ -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.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<@NonNull CachingIterator> fIterators = new ArrayList<>();
+
+    private final Comparator<ITimeEvent> fComparator;
+
+    /**
+     * Constructor
+     *
+     * @param contributors
+     *            the entries to aggregate
+     * @param comparator
+     *            The comparator to sort time events
+     */
+    public AggregateEventIterator(@NonNull List<ITimeGraphEntry> contributors, Comparator<ITimeEvent> 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<ITimeGraphEntry> contributors, long startTime, long endTime, long duration, Comparator<ITimeEvent> 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<CachingIterator> 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
new file mode 100644 (file)
index 0000000..eeafe6e
--- /dev/null
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * 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<ITimeGraphEntry> fContributors = new ArrayList<>();
+
+    private static final Comparator<ITimeEvent> COMPARATOR = new Comparator<ITimeEvent>() {
+        @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);
+    }
+
+    @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
new file mode 100644 (file)
index 0000000..46c4b6b
--- /dev/null
@@ -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.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.
+ * <ul>
+ * <li>peek() allows reading the head without removing it</li>
+ * <li>trim() allows removing a bit of the first event</li>
+ * </ul>
+ *
+ * @author Matthew Khouzam
+ */
+class CachingIterator implements Iterator<@NonNull ITimeEvent>, Comparable<CachingIterator> {
+    private ITimeEvent fEvent;
+    private @NonNull Iterator<@NonNull ? extends ITimeEvent> fIterator;
+    private final Comparator<ITimeEvent> fComparator;
+
+    public CachingIterator(@NonNull Iterator<@NonNull ? extends ITimeEvent> iterator, Comparator<ITimeEvent> 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
index ad1647bb2bd906244687d84bfd22f10982c1abde..0aad6c0b4e6e7d374a4b180edce21432e215c09b 100644 (file)
@@ -189,7 +189,7 @@ public class ResourcesPresentationProvider extends TimeGraphPresentationProvider
 
                         try {
                             List<ITmfStateInterval> fullState = ss.queryFullState(event.getTime());
-                            List<Integer> irqQuarks = ss.getQuarks(Attributes.RESOURCES, Attributes.IRQS, "*"); //$NON-NLS-1$
+                            List<Integer> irqQuarks = ss.getQuarks(Attributes.CPUS, Integer.toString(cpu), Attributes.IRQS, "*"); //$NON-NLS-1$
 
                             for (int irqQuark : irqQuarks) {
                                 if (fullState.get(irqQuark).getStateValue().unboxInt() == cpu) {
@@ -212,7 +212,7 @@ public class ResourcesPresentationProvider extends TimeGraphPresentationProvider
 
                         try {
                             List<ITmfStateInterval> fullState = ss.queryFullState(event.getTime());
-                            List<Integer> softIrqQuarks = ss.getQuarks(Attributes.RESOURCES, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$
+                            List<Integer> 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) {
index 7e0acd49a47bb88cb5fdbbbebfd8379d647b9ce9..2782db468197a6086ba4411a7f698fc7678bdd54 100644 (file)
@@ -21,6 +21,8 @@ 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.tracecompass.analysis.os.linux.core.kernelanalysis.Attributes;
@@ -68,6 +70,7 @@ public class ResourcesView extends AbstractStateSystemTimeGraphView {
         setFilterColumns(FILTER_COLUMN_NAMES);
         setFilterLabelProvider(new ResourcesFilterLabelProvider());
         setEntryComparator(new ResourcesEntryComparator());
+        setAutoExpandLevel(1);
     }
 
     private static class ResourcesEntryComparator implements Comparator<ITimeGraphEntry> {
@@ -143,7 +146,8 @@ public class ResourcesView extends AbstractStateSystemTimeGraphView {
                 return;
             }
             long end = ssq.getCurrentEndTime();
-            if (start == end && !complete) { // when complete execute one last time regardless of end time
+            if (start == end && !complete) {
+                // when complete execute one last time regardless of end time
                 continue;
             }
             long endTime = end + 1;
@@ -156,44 +160,8 @@ public class ResourcesView extends AbstractStateSystemTimeGraphView {
             } else {
                 traceEntry.updateEndTime(endTime);
             }
-
             List<Integer> cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$
-            for (Integer cpuQuark : cpuQuarks) {
-                int cpu = Integer.parseInt(ssq.getAttributeName(cpuQuark));
-                ResourcesEntry entry = entryMap.get(cpuQuark);
-                if (entry == null) {
-                    entry = new ResourcesEntry(cpuQuark, trace, startTime, endTime, Type.CPU, cpu);
-                    entryMap.put(cpuQuark, entry);
-                    traceEntry.addChild(entry);
-                } else {
-                    entry.updateEndTime(endTime);
-                }
-            }
-            List<Integer> irqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.IRQS, "*"); //$NON-NLS-1$
-            for (Integer irqQuark : irqQuarks) {
-                int irq = Integer.parseInt(ssq.getAttributeName(irqQuark));
-                ResourcesEntry entry = entryMap.get(irqQuark);
-                if (entry == null) {
-                    entry = new ResourcesEntry(irqQuark, trace, startTime, endTime, Type.IRQ, irq);
-                    entryMap.put(irqQuark, entry);
-                    traceEntry.addChild(entry);
-                } else {
-                    entry.updateEndTime(endTime);
-                }
-            }
-            List<Integer> softIrqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$
-            for (Integer softIrqQuark : softIrqQuarks) {
-                int softIrq = Integer.parseInt(ssq.getAttributeName(softIrqQuark));
-                ResourcesEntry entry = entryMap.get(softIrqQuark);
-                if (entry == null) {
-                    entry = new ResourcesEntry(softIrqQuark, trace, startTime, endTime, Type.SOFT_IRQ, softIrq);
-                    entryMap.put(softIrqQuark, entry);
-                    traceEntry.addChild(entry);
-                } else {
-                    entry.updateEndTime(endTime);
-                }
-            }
-
+            createCpuEntriesWithQuark(trace, ssq, entryMap, traceEntry, startTime, endTime, cpuQuarks);
             if (parentTrace.equals(getTrace())) {
                 refresh();
             }
@@ -205,111 +173,220 @@ public class ResourcesView extends AbstractStateSystemTimeGraphView {
                 @Override
                 public void handle(List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState) {
                     for (ITimeGraphEntry child : traceEntryChildren) {
-                        if (monitor.isCanceled()) {
+                        if (!populateEventsRecursively(fullStates, prevFullState, child).isOK()) {
                             return;
                         }
-                        if (child instanceof TimeGraphEntry) {
-                            TimeGraphEntry entry = (TimeGraphEntry) child;
-                            List<ITimeEvent> eventList = getEventList(entry, ssq, fullStates, prevFullState, monitor);
-                            if (eventList != null) {
-                                for (ITimeEvent event : eventList) {
-                                    entry.addEvent(event);
-                                }
+                    }
+                }
+
+                private IStatus populateEventsRecursively(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, ITimeGraphEntry entry) {
+                    if (monitor.isCanceled()) {
+                        return Status.CANCEL_STATUS;
+                    }
+                    if (entry instanceof TimeGraphEntry) {
+                        TimeGraphEntry timeGraphEntry = (TimeGraphEntry) entry;
+                        List<ITimeEvent> eventList = getEventList(timeGraphEntry, ssq, fullStates, prevFullState, monitor);
+                        if (eventList != null) {
+                            for (ITimeEvent event : eventList) {
+                                timeGraphEntry.addEvent(event);
                             }
                         }
                     }
+                    for (ITimeGraphEntry 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<Integer, ResourcesEntry> entryMap, TimeGraphEntry traceEntry, long startTime, long endTime, List<Integer> 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<Integer> irqQuarks = ssq.getQuarks(Attributes.CPUS, cpuName, Attributes.IRQS, "*"); //$NON-NLS-1$
+            createCpuInterruptEntryWithQuark(trace, ssq, entryMap, startTime, endTime, traceEntry, cpuEntry, irqQuarks, Type.IRQ);
+            List<Integer> 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<Integer, ResourcesEntry> entryMap,
+            long startTime, long endTime,
+            TimeGraphEntry traceEntry, ResourcesEntry cpuEntry,
+            List<Integer> 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);
+                            break;
+                        }
+                    }
+                }
+                if (!found) {
+                    AggregateResourcesEntry aggregateInterruptEntry = new AggregateResourcesEntry(trace, startTime, endTime, type, resourceId);
+                    aggregateInterruptEntry.addContributor(interruptEntry);
+                    traceEntry.addChild(aggregateInterruptEntry);
+                }
+            } else {
+                interruptEntry.updateEndTime(endTime);
+            }
+        }
     }
 
     @Override
     protected @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry entry, ITmfStateSystem ssq,
             @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
         ResourcesEntry resourcesEntry = (ResourcesEntry) entry;
-        List<ITimeEvent> eventList = null;
         int quark = resourcesEntry.getQuark();
 
         if (resourcesEntry.getType().equals(Type.CPU)) {
-            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 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<ITimeEvent> createCpuEventsList(TimeGraphEntry entry, ITmfStateSystem ssq, List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState, IProgressMonitor monitor, int quark) {
+        List<ITimeEvent> 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;
+        }
+        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<ITmfStateInterval> fullState : fullStates) {
+            if (monitor.isCanceled()) {
                 return null;
             }
-            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<ITmfStateInterval> 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 {
-                    eventList.add(new NullTimeEvent(entry, time, duration));
-                }
-                lastStartTime = time;
-                lastEndTime = time + duration;
+            if (statusQuark >= fullState.size()) {
+                /* No information on this CPU (yet?), skip it for now */
+                continue;
             }
-        } else if (resourcesEntry.getType().equals(Type.IRQ) || resourcesEntry.getType().equals(Type.SOFT_IRQ)) {
-            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<ITmfStateInterval> 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));
-                    }
-                    eventList.add(new NullTimeEvent(entry, time, duration));
-                    lastIsNull = true;
+            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));
                 }
-                lastStartTime = time;
-                lastEndTime = time + duration;
+                eventList.add(new TimeEvent(entry, time, duration, status));
+            } else {
+                eventList.add(new NullTimeEvent(entry, time, duration));
             }
+            lastStartTime = time;
+            lastEndTime = time + duration;
         }
+        return eventList;
+    }
 
+    private static List<ITimeEvent> createIrqEventsList(TimeGraphEntry entry, List<List<ITmfStateInterval>> fullStates, List<ITmfStateInterval> prevFullState, IProgressMonitor monitor, int quark) {
+        List<ITimeEvent> eventList;
+        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<ITmfStateInterval> 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));
+                }
+                eventList.add(new NullTimeEvent(entry, time, duration));
+                lastIsNull = true;
+            }
+            lastStartTime = time;
+            lastEndTime = time + duration;
+        }
         return eventList;
     }
 
index 17c21c845e99537a9df3817c45565d1f8828a179..bd7b1f054b684a67f948abf936a2d74f0ce98b32 100644 (file)
@@ -26,13 +26,14 @@ import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
 import org.eclipse.tracecompass.tmf.ctf.core.tests.shared.CtfTmfTestTraceUtils;
 import org.eclipse.tracecompass.tmf.ctf.core.trace.CtfTmfTrace;
+import org.junit.Test;
 
 /**
  * Small program to regenerate the values used in "TestValues.java" from the
  * current LTTng-kernel state provider.
  *
- * It will write its output the a file called 'TestValues<something>.java' in your
- * temporary files directory.
+ * It will write its output the a file called 'TestValues<something>.java' in
+ * your temporary files directory.
  *
  * @author Alexandre Montplaisir
  */
@@ -42,6 +43,17 @@ public class GenerateTestValues {
     private static final long targetTimestamp = 18670067372290L + 1331649577946812237L;
     private static final String INDENT = "    ";
 
+    /**
+     * Test wrapper to run main properly
+     *
+     * @throws Exception
+     *             we're messing with exception
+     */
+    @Test
+    public void test() throws Exception {
+        main(null);
+    }
+
     /**
      * Run the program
      *
index 0f869c1beea9af8709a5b952559b70e8b6b9fb4b..d9e2218c02eeccfcd0801b21e2ff7ba4727ef52c 100644 (file)
@@ -163,7 +163,7 @@ public abstract class StateSystemTest {
         assertNotNull(ss);
 
         try {
-            int quark = ss.getQuarkAbsolute(Attributes.RESOURCES, Attributes.IRQS, "1");
+            int quark = ss.getQuarkAbsolute(Attributes.CPUS, Integer.toString(0), Attributes.IRQS, "1");
             long ts1 = ss.getStartTime(); /* start of the trace */
             long ts2 = startTime + 20L * NANOSECS_PER_SEC; /* invalid, but ignored */
 
index 1875b5cb4f6459d6906facf6cd030ea993474898..72b125af386ddcf7a5785fc9501f27e01c3fb8e0 100644 (file)
@@ -24,7 +24,8 @@ import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
  * @author Alexandre Montplaisir
  */
 interface TestValues {
-    int size = 1032;
+
+    int size = 1036;
 
     long[] startTimes = {
         1331668247314038062L,
@@ -62,12 +63,13 @@ interface TestValues {
         1331668248014184526L,
         1331668248014130616L,
         1331668247314038062L,
-        1331668247314038062L,
-        1331668248011125682L,
+        1331668248011090056L,
         1331668247314038062L,
         1331668247931793142L,
         1331668247930941981L,
-        1331668247959041965L,
+        1331668247314038062L,
+        1331668248011125682L,
+        1331668247959024716L,
         1331668248011129576L,
         1331668247314038062L,
         1331668247314038062L,
@@ -110,6 +112,7 @@ interface TestValues {
         1331668247999327778L,
         1331668247318631139L,
         1331668247314038062L,
+        1331668247959041965L,
         1331668247960265258L,
         1331668247314038062L,
         1331668247903884233L,
@@ -135,6 +138,7 @@ interface TestValues {
         1331668247314038062L,
         1331668247330548245L,
         1331668247314038062L,
+        1331668247919182446L,
         1331668247340039213L,
         1331668247340083580L,
         1331668247966976915L,
@@ -264,6 +268,7 @@ interface TestValues {
         1331668247926367737L,
         1331668247423543945L,
         1331668247314038062L,
+        1331668247314038062L,
         1331668247619316825L,
         1331668247619491008L,
         1331668247314038062L,
@@ -1097,12 +1102,13 @@ interface TestValues {
         1331668248014548923L,
         1331668248014188534L,
         1331668259054285979L,
-        1331668259054285979L,
         1331668248015040151L,
         1331668259054285979L,
         1331668248482983146L,
         1331668248482983146L,
-        1331668248015041609L,
+        1331668259054285979L,
+        1331668248015170799L,
+        1331668248015172434L,
         1331668248015176320L,
         1331668259054285979L,
         1331668259054285979L,
@@ -1145,6 +1151,7 @@ interface TestValues {
         1331668248016645047L,
         1331668252843104826L,
         1331668259054285979L,
+        1331668248015041609L,
         1331668248486545657L,
         1331668259054285979L,
         1331668248502954816L,
@@ -1170,6 +1177,7 @@ interface TestValues {
         1331668259054285979L,
         1331668259054285979L,
         1331668259054285979L,
+        1331668248019005964L,
         1331668257323835062L,
         1331668257323879563L,
         1331668248021867385L,
@@ -1299,6 +1307,7 @@ interface TestValues {
         1331668248424394073L,
         1331668259054285979L,
         1331668259054285979L,
+        1331668259054285979L,
         1331668248140683324L,
         1331668248140686546L,
         1331668259054285979L,
@@ -2134,7 +2143,6 @@ interface TestValues {
         TmfStateValue.nullValue(),
         TmfStateValue.nullValue(),
         TmfStateValue.nullValue(),
-        TmfStateValue.nullValue(),
         TmfStateValue.newValueInt(1),
         TmfStateValue.newValueInt(20),
         TmfStateValue.nullValue(),
@@ -2146,6 +2154,8 @@ interface TestValues {
         TmfStateValue.nullValue(),
         TmfStateValue.nullValue(),
         TmfStateValue.nullValue(),
+        TmfStateValue.nullValue(),
+        TmfStateValue.nullValue(),
         TmfStateValue.newValueString("sys_poll"),
         TmfStateValue.newValueString("lttng-consumerd"),
         TmfStateValue.nullValue(),
@@ -2182,6 +2192,7 @@ interface TestValues {
         TmfStateValue.nullValue(),
         TmfStateValue.nullValue(),
         TmfStateValue.nullValue(),
+        TmfStateValue.nullValue(),
         TmfStateValue.newValueInt(1),
         TmfStateValue.newValueInt(20),
         TmfStateValue.newValueString("sys_poll"),
@@ -2209,6 +2220,7 @@ interface TestValues {
         TmfStateValue.nullValue(),
         TmfStateValue.nullValue(),
         TmfStateValue.nullValue(),
+        TmfStateValue.nullValue(),
         TmfStateValue.newValueInt(1),
         TmfStateValue.newValueInt(20),
         TmfStateValue.nullValue(),
@@ -2337,6 +2349,7 @@ interface TestValues {
         TmfStateValue.nullValue(),
         TmfStateValue.nullValue(),
         TmfStateValue.nullValue(),
+        TmfStateValue.nullValue(),
         TmfStateValue.newValueInt(1),
         TmfStateValue.newValueInt(20),
         TmfStateValue.newValueString("sys_poll"),
@@ -3130,6 +3143,5 @@ interface TestValues {
         TmfStateValue.nullValue(),
         TmfStateValue.nullValue(),
     };
-
 }
 
This page took 0.042638 seconds and 5 git commands to generate.