gdbtrace: Move plugins to the Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.kernel.ui / src / org / eclipse / linuxtools / internal / lttng2 / kernel / ui / views / controlflow / ControlFlowView.java
index fb6eb79bba16c17dc7b9cd56b8e1e22278b672ef..3627e80aa9e8eff4edb536512fb2f94e6ead7813 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012, 2013 Ericsson, École Polytechnique de Montréal
+ * Copyright (c) 2012, 2014 Ericsson, École Polytechnique de Montréal
  *
  * All rights reserved. This program and the accompanying materials are
  * made available under the terms of the Eclipse Public License v1.0 which
 package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.controlflow;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.action.IToolBarManager;
 import org.eclipse.jface.dialogs.IDialogSettings;
 import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes;
 import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Activator;
 import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Messages;
-import org.eclipse.linuxtools.lttng2.kernel.core.trace.LttngKernelTrace;
-import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
-import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
-import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
-import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
-import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
-import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
-import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
+import org.eclipse.linuxtools.lttng2.kernel.core.analysis.LttngKernelAnalysisModule;
+import org.eclipse.linuxtools.statesystem.core.ITmfStateSystem;
+import org.eclipse.linuxtools.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.StateValueTypeException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.TimeRangeException;
+import org.eclipse.linuxtools.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.linuxtools.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.linuxtools.tmf.core.statesystem.TmfStateSystemAnalysisModule;
 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
 import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
 import org.eclipse.linuxtools.tmf.ui.views.timegraph.AbstractTimeGraphView;
@@ -79,6 +83,9 @@ public class ControlFlowView extends AbstractTimeGraphView {
             TID_COLUMN
     };
 
+    // Timeout between updates in the build thread in ms
+    private static final long BUILD_UPDATE_TIMEOUT = 500;
+
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
@@ -91,18 +98,31 @@ public class ControlFlowView extends AbstractTimeGraphView {
         setTreeColumns(COLUMN_NAMES);
         setTreeLabelProvider(new ControlFlowTreeLabelProvider());
         setFilterColumns(FILTER_COLUMN_NAMES);
+        setFilterLabelProvider(new ControlFlowFilterLabelProvider());
         setEntryComparator(new ControlFlowEntryComparator());
     }
 
     @Override
     protected void fillLocalToolBar(IToolBarManager manager) {
+        super.fillLocalToolBar(manager);
         IDialogSettings settings = Activator.getDefault().getDialogSettings();
         IDialogSettings section = settings.getSection(getClass().getName());
         if (section == null) {
             section = settings.addNewSection(getClass().getName());
         }
-        manager.add(getTimeGraphCombo().getTimeGraphViewer().getHideArrowsAction(section));
-        super.fillLocalToolBar(manager);
+
+        IAction hideArrowsAction = getTimeGraphCombo().getTimeGraphViewer().getHideArrowsAction(section);
+        manager.add(hideArrowsAction);
+
+        IAction followArrowBwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowBwdAction();
+        followArrowBwdAction.setText(Messages.ControlFlowView_followCPUBwdText);
+        followArrowBwdAction.setToolTipText(Messages.ControlFlowView_followCPUBwdText);
+        manager.add(followArrowBwdAction);
+
+        IAction followArrowFwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowFwdAction();
+        followArrowFwdAction.setText(Messages.ControlFlowView_followCPUFwdText);
+        followArrowFwdAction.setToolTipText(Messages.ControlFlowView_followCPUFwdText);
+        manager.add(followArrowFwdAction);
     }
 
     @Override
@@ -180,161 +200,203 @@ public class ControlFlowView extends AbstractTimeGraphView {
 
     }
 
+    private static class ControlFlowFilterLabelProvider extends TreeLabelProvider {
+
+        @Override
+        public String getColumnText(Object element, int columnIndex) {
+            ControlFlowEntry entry = (ControlFlowEntry) element;
+
+            if (columnIndex == 0) {
+                return entry.getName();
+            } else if (columnIndex == 1) {
+                return Integer.toString(entry.getThreadId());
+            }
+            return ""; //$NON-NLS-1$
+        }
+
+    }
+
     // ------------------------------------------------------------------------
     // Internal
     // ------------------------------------------------------------------------
 
     @Override
-    protected void buildEventList(final ITmfTrace trace, IProgressMonitor monitor) {
-        setStartTime(Long.MAX_VALUE);
-        setEndTime(Long.MIN_VALUE);
+    protected void buildEventList(final ITmfTrace trace, ITmfTrace parentTrace, IProgressMonitor monitor) {
+        if (trace == null) {
+            return;
+        }
+        ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, LttngKernelAnalysisModule.ID);
+        if (ssq == null) {
+            return;
+        }
+
+        List<ControlFlowEntry> entryList = new ArrayList<>();
+        Map<Integer, ControlFlowEntry> entryMap = new HashMap<>();
+
+        long start = ssq.getStartTime();
+        setStartTime(Math.min(getStartTime(), start));
 
-        ArrayList<TimeGraphEntry> rootList = new ArrayList<TimeGraphEntry>();
-        for (ITmfTrace aTrace : fTraceManager.getActiveTraceSet()) {
+        boolean complete = false;
+        while (!complete) {
             if (monitor.isCanceled()) {
                 return;
             }
-            if (aTrace instanceof LttngKernelTrace) {
-                ArrayList<TimeGraphEntry> entryList = new ArrayList<TimeGraphEntry>();
-                LttngKernelTrace ctfKernelTrace = (LttngKernelTrace) aTrace;
-                ITmfStateSystem ssq = ctfKernelTrace.getStateSystems().get(LttngKernelTrace.STATE_ID);
-                if (!ssq.waitUntilBuilt()) {
+            complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
+            if (ssq.isCancelled()) {
+                return;
+            }
+            long end = ssq.getCurrentEndTime();
+            if (start == end && !complete) { // when complete execute one last time regardless of end time
+                continue;
+            }
+            setEndTime(Math.max(getEndTime(), end + 1));
+            List<Integer> threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$
+            for (int threadQuark : threadQuarks) {
+                if (monitor.isCanceled()) {
                     return;
                 }
-                long start = ssq.getStartTime();
-                long end = ssq.getCurrentEndTime() + 1;
-                setStartTime(Math.min(getStartTime(), start));
-                setEndTime(Math.max(getEndTime(), end));
-                List<Integer> threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$
-                for (int threadQuark : threadQuarks) {
+                String threadName = ssq.getAttributeName(threadQuark);
+                int threadId = -1;
+                try {
+                    threadId = Integer.parseInt(threadName);
+                } catch (NumberFormatException e1) {
+                    continue;
+                }
+                if (threadId <= 0) { // ignore the 'unknown' (-1) and swapper (0) threads
+                    continue;
+                }
+
+                int execNameQuark;
+                List<ITmfStateInterval> execNameIntervals;
+                try {
+                    execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME);
+                    execNameIntervals = ssq.queryHistoryRange(execNameQuark, start, end);
+                } catch (AttributeNotFoundException e) {
+                    /* No information on this thread (yet?), skip it for now */
+                    continue;
+                } catch (StateSystemDisposedException e) {
+                    /* State system is closing down, no point continuing */
+                    break;
+                }
+
+                for (ITmfStateInterval execNameInterval : execNameIntervals) {
                     if (monitor.isCanceled()) {
                         return;
                     }
-                    String threadName = ssq.getAttributeName(threadQuark);
-                    int threadId = -1;
-                    try {
-                        threadId = Integer.parseInt(threadName);
-                    } catch (NumberFormatException e1) {
-                        continue;
-                    }
-                    if (threadId == 0) { // ignore the swapper thread
-                        continue;
-                    }
-                    int execNameQuark = -1;
-                    try {
-                        try {
-                            execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME);
-                        } catch (AttributeNotFoundException e) {
-                            continue;
-                        }
-                        int ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID);
-                        List<ITmfStateInterval> execNameIntervals = ssq.queryHistoryRange(execNameQuark, start, end - 1);
-                        // use monitor when available in api
-                        if (monitor.isCanceled()) {
-                            return;
-                        }
-                        TimeGraphEntry entry = null;
-                        for (ITmfStateInterval execNameInterval : execNameIntervals) {
-                            if (monitor.isCanceled()) {
-                                return;
+                    ControlFlowEntry entry = entryMap.get(threadId);
+                    if (!execNameInterval.getStateValue().isNull() &&
+                            execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) {
+                        String execName = execNameInterval.getStateValue().unboxStr();
+                        long startTime = execNameInterval.getStartTime();
+                        long endTime = execNameInterval.getEndTime() + 1;
+                        if (entry == null) {
+                            ITmfStateInterval ppidInterval = null;
+                            try {
+                                int ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID);
+                                ppidInterval = ssq.querySingleState(startTime, ppidQuark);
+                            } catch (AttributeNotFoundException e) {
+                                /* No info, keep PPID at -1 */
+                            } catch (StateSystemDisposedException e) {
+                                /* SS is closing down, time to bail */
+                                break;
                             }
-                            if (!execNameInterval.getStateValue().isNull() &&
-                                    execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) {
-                                String execName = execNameInterval.getStateValue().unboxStr();
-                                long startTime = execNameInterval.getStartTime();
-                                long endTime = execNameInterval.getEndTime() + 1;
-                                int ppid = -1;
-                                if (ppidQuark != -1) {
-                                    ITmfStateInterval ppidInterval = ssq.querySingleState(startTime, ppidQuark);
-                                    ppid = ppidInterval.getStateValue().unboxInt();
-                                }
-                                if (entry == null) {
-                                    entry = new ControlFlowEntry(threadQuark, ctfKernelTrace, execName, threadId, ppid, startTime, endTime);
-                                    entryList.add(entry);
-                                } else {
-                                    // update the name of the entry to the
-                                    // latest execName
-                                    entry.setName(execName);
-                                }
-                                entry.addEvent(new TimeEvent(entry, startTime, endTime - startTime));
-                            } else {
-                                entry = null;
+                            int ppid = -1;
+                            if (!(ppidInterval == null) && !ppidInterval.getStateValue().isNull()) {
+                                ppid = ppidInterval.getStateValue().unboxInt();
                             }
+                            entry = new ControlFlowEntry(threadQuark, trace, execName, threadId, ppid, startTime, endTime);
+                            entryList.add(entry);
+                            entryMap.put(threadId, entry);
+                        } else {
+                            // update the name of the entry to the latest
+                            // execName
+                            entry.setName(execName);
+                            entry.updateEndTime(endTime);
                         }
-                    } catch (AttributeNotFoundException e) {
-                        e.printStackTrace();
-                    } catch (TimeRangeException e) {
-                        e.printStackTrace();
-                    } catch (StateValueTypeException e) {
-                        e.printStackTrace();
-                    } catch (StateSystemDisposedException e) {
-                        /* Ignored */
+                    } else {
+                        entryMap.remove(threadId);
                     }
                 }
-                buildTree(entryList, rootList);
             }
-            Collections.sort(rootList, getEntryComparator());
-            putEntryList(trace, (ArrayList<TimeGraphEntry>) rootList.clone());
 
-            if (trace.equals(getTrace())) {
+            updateTree(entryList, parentTrace);
+
+            if (parentTrace.equals(getTrace())) {
                 refresh();
             }
-        }
-        for (TimeGraphEntry entry : rootList) {
-            if (monitor.isCanceled()) {
-                return;
+
+            for (ControlFlowEntry entry : entryList) {
+                if (monitor.isCanceled()) {
+                    return;
+                }
+                buildStatusEvents(entry.getTrace(), entry, monitor, start, end);
             }
-            buildStatusEvents(trace, entry, monitor);
+
+            start = end;
         }
     }
 
-    private static void buildTree(ArrayList<TimeGraphEntry> entryList,
-            ArrayList<TimeGraphEntry> rootList) {
-        for (TimeGraphEntry listentry : entryList) {
-            ControlFlowEntry entry = (ControlFlowEntry) listentry;
-            boolean root = true;
-            if (entry.getParentThreadId() > 0) {
-                for (TimeGraphEntry parententry : entryList) {
-                    ControlFlowEntry parent = (ControlFlowEntry) parententry;
+    private void updateTree(List<ControlFlowEntry> entryList, ITmfTrace parentTrace) {
+        List<TimeGraphEntry> rootListToAdd = new ArrayList<>();
+        List<TimeGraphEntry> rootListToRemove = new ArrayList<>();
+        List<TimeGraphEntry> rootList = getEntryList(parentTrace);
+
+        for (ControlFlowEntry entry : entryList) {
+            boolean root = (entry.getParent() == null);
+            if (root && entry.getParentThreadId() > 0) {
+                for (ControlFlowEntry parent : entryList) {
                     if (parent.getThreadId() == entry.getParentThreadId() &&
                             entry.getStartTime() >= parent.getStartTime() &&
                             entry.getStartTime() <= parent.getEndTime()) {
                         parent.addChild(entry);
                         root = false;
+                        if (rootList != null && rootList.contains(entry)) {
+                            rootListToRemove.add(entry);
+                        }
                         break;
                     }
                 }
             }
-            if (root) {
-                rootList.add(entry);
+            if (root && (rootList == null || !rootList.contains(entry))) {
+                rootListToAdd.add(entry);
             }
         }
+
+        addToEntryList(parentTrace, rootListToAdd);
+        removeFromEntryList(parentTrace, rootListToRemove);
     }
 
-    private void buildStatusEvents(ITmfTrace trace, TimeGraphEntry entry, IProgressMonitor monitor) {
-        ITmfStateSystem ssq = entry.getTrace().getStateSystems().get(LttngKernelTrace.STATE_ID);
+    private void buildStatusEvents(ITmfTrace trace, ControlFlowEntry entry, IProgressMonitor monitor, long start, long end) {
+        if (start < entry.getEndTime() && end > entry.getStartTime()) {
+            ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), LttngKernelAnalysisModule.ID);
+            if (ssq == null) {
+                return;
+            }
 
-        long start = ssq.getStartTime();
-        long end = ssq.getCurrentEndTime() + 1;
-        long resolution = Math.max(1, (end - start) / getDisplayWidth());
-        List<ITimeEvent> eventList = getEventList(entry, entry.getStartTime(), entry.getEndTime(), resolution, monitor);
-        if (monitor.isCanceled()) {
-            return;
-        }
-        entry.setEventList(eventList);
-        if (trace.equals(getTrace())) {
-            redraw();
+            long startTime = Math.max(start, entry.getStartTime());
+            long endTime = Math.min(end + 1, entry.getEndTime());
+            long resolution = Math.max(1, (end - ssq.getStartTime()) / getDisplayWidth());
+            List<ITimeEvent> eventList = getEventList(entry, startTime, endTime, resolution, monitor);
+            if (eventList == null) {
+                return;
+            }
+            for (ITimeEvent event : eventList) {
+                entry.addEvent(event);
+            }
+            if (trace.equals(getTrace())) {
+                redraw();
+            }
         }
         for (ITimeGraphEntry child : entry.getChildren()) {
             if (monitor.isCanceled()) {
                 return;
             }
-            buildStatusEvents(trace, (TimeGraphEntry) child, monitor);
+            buildStatusEvents(trace, (ControlFlowEntry) child, monitor, start, end);
         }
     }
 
     @Override
-    protected List<ITimeEvent> getEventList(TimeGraphEntry tgentry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
+    protected @Nullable List<ITimeEvent> getEventList(TimeGraphEntry tgentry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
         List<ITimeEvent> eventList = null;
         if (!(tgentry instanceof ControlFlowEntry)) {
             return eventList;
@@ -345,11 +407,14 @@ public class ControlFlowView extends AbstractTimeGraphView {
         if (realEnd <= realStart) {
             return null;
         }
-        ITmfStateSystem ssq = entry.getTrace().getStateSystems().get(LttngKernelTrace.STATE_ID);
+        ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), LttngKernelAnalysisModule.ID);
+        if (ssq == null) {
+            return null;
+        }
         try {
             int statusQuark = ssq.getQuarkRelative(entry.getThreadQuark(), Attributes.STATUS);
             List<ITmfStateInterval> statusIntervals = ssq.queryHistoryRange(statusQuark, realStart, realEnd - 1, resolution, monitor);
-            eventList = new ArrayList<ITimeEvent>(statusIntervals.size());
+            eventList = new ArrayList<>(statusIntervals.size());
             long lastEndTime = -1;
             for (ITmfStateInterval statusInterval : statusIntervals) {
                 if (monitor.isCanceled()) {
@@ -369,9 +434,7 @@ public class ControlFlowView extends AbstractTimeGraphView {
                 eventList.add(new TimeEvent(entry, time, duration, status));
                 lastEndTime = time + duration;
             }
-        } catch (AttributeNotFoundException e) {
-            e.printStackTrace();
-        } catch (TimeRangeException e) {
+        } catch (AttributeNotFoundException | TimeRangeException e) {
             e.printStackTrace();
         } catch (StateSystemDisposedException e) {
             /* Ignored */
@@ -382,8 +445,8 @@ public class ControlFlowView extends AbstractTimeGraphView {
     /**
      * Returns a value corresponding to the selected entry.
      *
-     * Used in conjunction with selectEntry to change the selected entry. If one
-     * of these methods is overridden in child class, then both should be.
+     * Used in conjunction with synchingToTime to change the selected entry. If
+     * one of these methods is overridden in child class, then both should be.
      *
      * @param time
      *            The currently selected time
@@ -391,36 +454,39 @@ public class ControlFlowView extends AbstractTimeGraphView {
      */
     private int getSelectionValue(long time) {
         int thread = -1;
-        for (ITmfTrace trace : fTraceManager.getActiveTraceSet()) {
+        ITmfTrace[] traces = TmfTraceManager.getTraceSet(getTrace());
+        if (traces == null) {
+            return thread;
+        }
+        for (ITmfTrace trace : traces) {
             if (thread > 0) {
                 break;
             }
-            if (trace instanceof LttngKernelTrace) {
-                LttngKernelTrace ctfKernelTrace = (LttngKernelTrace) trace;
-                ITmfStateSystem ssq = ctfKernelTrace.getStateSystems().get(LttngKernelTrace.STATE_ID);
-                if (time >= ssq.getStartTime() && time <= ssq.getCurrentEndTime()) {
-                    List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
-                    for (int currentThreadQuark : currentThreadQuarks) {
-                        try {
-                            ITmfStateInterval currentThreadInterval = ssq.querySingleState(time, currentThreadQuark);
-                            int currentThread = currentThreadInterval.getStateValue().unboxInt();
-                            if (currentThread > 0) {
-                                int statusQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThread), Attributes.STATUS);
-                                ITmfStateInterval statusInterval = ssq.querySingleState(time, statusQuark);
-                                if (statusInterval.getStartTime() == time) {
-                                    thread = currentThread;
-                                    break;
-                                }
+            if (trace == null) {
+                continue;
+            }
+            ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, LttngKernelAnalysisModule.ID);
+            if (ssq == null) {
+                continue;
+            }
+            if (time >= ssq.getStartTime() && time <= ssq.getCurrentEndTime()) {
+                List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
+                for (int currentThreadQuark : currentThreadQuarks) {
+                    try {
+                        ITmfStateInterval currentThreadInterval = ssq.querySingleState(time, currentThreadQuark);
+                        int currentThread = currentThreadInterval.getStateValue().unboxInt();
+                        if (currentThread > 0) {
+                            int statusQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThread), Attributes.STATUS);
+                            ITmfStateInterval statusInterval = ssq.querySingleState(time, statusQuark);
+                            if (statusInterval.getStartTime() == time) {
+                                thread = currentThread;
+                                break;
                             }
-                        } catch (AttributeNotFoundException e) {
-                            e.printStackTrace();
-                        } catch (TimeRangeException e) {
-                            e.printStackTrace();
-                        } catch (StateValueTypeException e) {
-                            e.printStackTrace();
-                        } catch (StateSystemDisposedException e) {
-                            /* Ignored */
                         }
+                    } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
+                        e.printStackTrace();
+                    } catch (StateSystemDisposedException e) {
+                        /* Ignored */
                     }
                 }
             }
@@ -446,57 +512,69 @@ public class ControlFlowView extends AbstractTimeGraphView {
 
     @Override
     protected List<ILinkEvent> getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
-        List<ILinkEvent> list = new ArrayList<ILinkEvent>();
+        List<ILinkEvent> list = new ArrayList<>();
         ITmfTrace[] traces = TmfTraceManager.getTraceSet(getTrace());
-        List<TimeGraphEntry> entryList = getEntryListMap().get(getTrace());
+        List<TimeGraphEntry> entryList = getEntryList(getTrace());
         if (traces == null || entryList == null) {
             return list;
         }
         for (ITmfTrace trace : traces) {
-            if (trace instanceof LttngKernelTrace) {
-                ITmfStateSystem ssq = trace.getStateSystems().get(LttngKernelTrace.STATE_ID);
-                try {
-                    long start = Math.max(startTime, ssq.getStartTime());
-                    long end = Math.min(endTime, ssq.getCurrentEndTime());
-                    if (end < start) {
-                        continue;
-                    }
-                    List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
-                    for (int currentThreadQuark : currentThreadQuarks) {
-                        List<ITmfStateInterval> currentThreadIntervals = ssq.queryHistoryRange(currentThreadQuark, start, end, resolution, monitor);
-                        int prevThread = 0;
-                        long prevEnd = 0;
-                        for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) {
-                            if (monitor.isCanceled()) {
-                                return null;
-                            }
-                            long time = currentThreadInterval.getStartTime();
-                            int thread = currentThreadInterval.getStateValue().unboxInt();
-                            if (thread > 0 && prevThread > 0 && thread != prevThread && time == prevEnd) {
-                                ITimeGraphEntry prevEntry = findEntry(entryList, trace, prevThread);
-                                ITimeGraphEntry nextEntry = findEntry(entryList, trace, thread);
-                                list.add(new TimeLinkEvent(prevEntry, nextEntry, time, 0, 0));
-                            }
+            if (trace == null) {
+                continue;
+            }
+            ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, LttngKernelAnalysisModule.ID);
+            if (ssq == null) {
+                continue;
+            }
+            try {
+                long start = Math.max(startTime, ssq.getStartTime());
+                long end = Math.min(endTime, ssq.getCurrentEndTime());
+                if (end < start) {
+                    continue;
+                }
+                List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
+                for (int currentThreadQuark : currentThreadQuarks) {
+                    // adjust the query range to include the previous and following intervals
+                    long qstart = Math.max(ssq.querySingleState(start, currentThreadQuark).getStartTime() - 1, ssq.getStartTime());
+                    long qend = Math.min(ssq.querySingleState(end, currentThreadQuark).getEndTime() + 1, ssq.getCurrentEndTime());
+                    List<ITmfStateInterval> currentThreadIntervals = ssq.queryHistoryRange(currentThreadQuark, qstart, qend, resolution, monitor);
+                    int prevThread = 0;
+                    long prevEnd = 0;
+                    long lastEnd = 0;
+                    for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) {
+                        if (monitor.isCanceled()) {
+                            return null;
+                        }
+                        long time = currentThreadInterval.getStartTime();
+                        if (time != lastEnd) {
+                            // don't create links where there are gaps in intervals due to the resolution
+                            prevThread = 0;
+                            prevEnd = 0;
+                        }
+                        int thread = currentThreadInterval.getStateValue().unboxInt();
+                        if (thread > 0 && prevThread > 0) {
+                            ITimeGraphEntry prevEntry = findEntry(entryList, trace, prevThread);
+                            ITimeGraphEntry nextEntry = findEntry(entryList, trace, thread);
+                            list.add(new TimeLinkEvent(prevEntry, nextEntry, prevEnd, time - prevEnd, 0));
+                        }
+                        lastEnd = currentThreadInterval.getEndTime() + 1;
+                        if (thread != 0) {
                             prevThread = thread;
-                            prevEnd = currentThreadInterval.getEndTime() + 1;
+                            prevEnd = lastEnd;
                         }
                     }
-                } catch (TimeRangeException e) {
-                    e.printStackTrace();
-                } catch (AttributeNotFoundException e) {
-                    e.printStackTrace();
-                } catch (StateValueTypeException e) {
-                    e.printStackTrace();
-                } catch (StateSystemDisposedException e) {
-                    /* Ignored */
                 }
+            } catch (TimeRangeException | AttributeNotFoundException | StateValueTypeException e) {
+                e.printStackTrace();
+            } catch (StateSystemDisposedException e) {
+                /* Ignored */
             }
         }
         return list;
     }
 
-    private ControlFlowEntry findEntry(List<TimeGraphEntry> entryList, ITmfTrace trace, int threadId) {
-        for (TimeGraphEntry entry : entryList) {
+    private ControlFlowEntry findEntry(List<? extends ITimeGraphEntry> entryList, ITmfTrace trace, int threadId) {
+        for (ITimeGraphEntry entry : entryList) {
             if (entry instanceof ControlFlowEntry) {
                 ControlFlowEntry controlFlowEntry = (ControlFlowEntry) entry;
                 if (controlFlowEntry.getThreadId() == threadId && controlFlowEntry.getTrace() == trace) {
This page took 0.032837 seconds and 5 git commands to generate.