lttng/tmf: add a "unit-less" representation of time in timechart
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.kernel.ui / src / org / eclipse / linuxtools / internal / lttng2 / kernel / ui / views / resources / ResourcesView.java
index 0f60fbea331757aacc9487761b2cec8b061ceca5..4001bad67d91f4198f6f2e38dc0dad8a73541100 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2012 Ericsson\r
- * \r
- * All rights reserved. This program and the accompanying materials are\r
- * made available under the terms of the Eclipse Public License v1.0 which\r
- * accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- * \r
- * Contributors:\r
- *   Patrick Tasse - Initial API and implementation\r
- *******************************************************************************/\r
-\r
-package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Map;\r
-\r
-import org.eclipse.linuxtools.lttng2.kernel.core.trace.Attributes;\r
-import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace;\r
-import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;\r
-import org.eclipse.linuxtools.tmf.core.event.TmfEvent;\r
-import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;\r
-import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;\r
-import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;\r
-import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;\r
-import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal;\r
-import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;\r
-import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemQuerier;\r
-import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;\r
-import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;\r
-import org.eclipse.linuxtools.tmf.ui.views.TmfView;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphProvider;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphViewer;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Display;\r
-\r
-public class ResourcesView extends TmfView {\r
-\r
-    // ------------------------------------------------------------------------\r
-    // Constants\r
-    // ------------------------------------------------------------------------\r
-\r
-    /**\r
-     * View ID.\r
-     */\r
-    public static final String ID = "org.eclipse.linuxtools.lttng2.kernel.ui.views.resources"; //$NON-NLS-1$\r
-\r
-    // ------------------------------------------------------------------------\r
-    // Fields\r
-    // ------------------------------------------------------------------------\r
-\r
-    // The time graph viewer\r
-    TimeGraphViewer fTimeGraphViewer;\r
-\r
-    // The selected experiment\r
-    private TmfExperiment<ITmfEvent> fSelectedExperiment;\r
-\r
-    // The time graph entry list\r
-    private ArrayList<ITimeGraphEntry> fEntryList;\r
-\r
-    // The start time\r
-    private long fStartTime;\r
-\r
-    // The end time\r
-    private long fEndTime;\r
-\r
-    // The display width\r
-    private int fDisplayWidth;\r
-\r
-    // ------------------------------------------------------------------------\r
-    // Classes\r
-    // ------------------------------------------------------------------------\r
-\r
-    private class GroupEntry implements ITimeGraphEntry {\r
-        public ITimeGraphEntry fParent;\r
-        public ArrayList<ITimeGraphEntry> fChildren;\r
-        public String fName;\r
-\r
-        public GroupEntry(ITimeGraphEntry parent, String name) {\r
-            fParent = parent;\r
-            fChildren = new ArrayList<ITimeGraphEntry>();\r
-            fName = name;\r
-        }\r
-\r
-        @Override\r
-        public ITimeGraphEntry getParent() {\r
-            return fParent;\r
-        }\r
-\r
-        @Override\r
-        public boolean hasChildren() {\r
-            return fChildren != null && fChildren.size() > 0;\r
-        }\r
-\r
-        @Override\r
-        public ITimeGraphEntry[] getChildren() {\r
-            return fChildren.toArray(new ITimeGraphEntry[0]);\r
-        }\r
-\r
-        @Override\r
-        public String getName() {\r
-            return fName;\r
-        }\r
-\r
-        @Override\r
-        public long getStartTime() {\r
-            return -1;\r
-        }\r
-\r
-        @Override\r
-        public long getStopTime() {\r
-            return -1;\r
-        }\r
-\r
-        @Override\r
-        public Iterator<ITimeEvent> getTimeEventsIterator() {\r
-            return null;\r
-        }\r
-\r
-        @Override\r
-        public <T extends ITimeEvent> Iterator<T> getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) {\r
-            return null;\r
-        }\r
-\r
-        public void addChild(ITimeGraphEntry entry) {\r
-            fChildren.add(entry);\r
-        }\r
-    }\r
-\r
-    // ------------------------------------------------------------------------\r
-    // Constructors\r
-    // ------------------------------------------------------------------------\r
-\r
-    public ResourcesView() {\r
-        super(ID);\r
-        fDisplayWidth = Display.getDefault().getBounds().width;\r
-    }\r
-\r
-    // ------------------------------------------------------------------------\r
-    // ViewPart\r
-    // ------------------------------------------------------------------------\r
-\r
-    /* (non-Javadoc)\r
-     * @see org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse.swt.widgets.Composite)\r
-     */\r
-    @Override\r
-    public void createPartControl(Composite parent) {\r
-        fTimeGraphViewer = new TimeGraphViewer(parent, SWT.NONE);\r
-\r
-        fTimeGraphViewer.setTimeGraphProvider(new TimeGraphProvider() {\r
-            @Override\r
-            public String getTraceClassName(ITimeGraphEntry trace) {\r
-                return "trace class"; //$NON-NLS-1$\r
-            }\r
-            \r
-            @Override\r
-            public String getStateName(StateColor color) {\r
-                return "state name"; //$NON-NLS-1$\r
-            }\r
-            \r
-            @Override\r
-            public String getEventName(ITimeEvent event, boolean upper, boolean extInfo) {\r
-                return "event name"; //$NON-NLS-1$\r
-            }\r
-            \r
-            @Override\r
-            public Map<String, String> getEventHoverToolTipInfo(ITimeEvent event) {\r
-                return new HashMap<String, String>();\r
-            }\r
-            \r
-            @Override\r
-            public StateColor getEventColor(ITimeEvent event) {\r
-                if (event.getTime() % 2 == 0) {\r
-                    return StateColor.BLACK;\r
-                } else {\r
-                    return StateColor.GRAY;\r
-                }\r
-            }\r
-        });\r
-\r
-        final Thread thread = new Thread() {\r
-            @Override\r
-            public void run() {\r
-                if (TmfExperiment.getCurrentExperiment() != null) {\r
-                    selectExperiment(TmfExperiment.getCurrentExperiment());\r
-                }\r
-            }\r
-        };\r
-        thread.start();\r
-    }\r
-\r
-    /* (non-Javadoc)\r
-     * @see org.eclipse.ui.part.WorkbenchPart#setFocus()\r
-     */\r
-    @Override\r
-    public void setFocus() {\r
-        fTimeGraphViewer.setFocus();\r
-    }\r
-\r
-    // ------------------------------------------------------------------------\r
-    // Signal handlers\r
-    // ------------------------------------------------------------------------\r
-\r
-    @TmfSignalHandler\r
-    public void experimentSelected(final TmfExperimentSelectedSignal<? extends TmfEvent> signal) {\r
-        if (signal.getExperiment().equals(fSelectedExperiment)) {\r
-            return;\r
-        }\r
-\r
-        final Thread thread = new Thread() {\r
-            @Override\r
-            public void run() {\r
-                selectExperiment(signal.getExperiment());\r
-            }};\r
-        thread.start();\r
-    }\r
-\r
-    @SuppressWarnings("unchecked")\r
-    private void selectExperiment(TmfExperiment<?> experiment) {\r
-        fStartTime = Long.MAX_VALUE;\r
-        fEndTime = Long.MIN_VALUE;\r
-        fSelectedExperiment = (TmfExperiment<ITmfEvent>) experiment;\r
-        fEntryList = new ArrayList<ITimeGraphEntry>();\r
-        for (ITmfTrace<?> trace : experiment.getTraces()) {\r
-            GroupEntry groupEntry = new GroupEntry(null, trace.getPath());\r
-            fEntryList.add(groupEntry);\r
-            refresh();\r
-            if (trace instanceof CtfKernelTrace) {\r
-                CtfKernelTrace ctfKernelTrace = (CtfKernelTrace) trace;\r
-                IStateSystemQuerier ssq = ctfKernelTrace.getStateSystem();\r
-                long start = ssq.getStartTime();\r
-                long end = ssq.getCurrentEndTime();\r
-                fStartTime = Math.min(fStartTime, start);\r
-                fEndTime = Math.max(fEndTime, end);\r
-                List<Integer> cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$\r
-                for (int cpuQuark : cpuQuarks) {\r
-                    String cpuName = "CPU " + ssq.getAttributeName(cpuQuark);\r
-                    ResourcesEntry entry = new ResourcesEntry(groupEntry, ctfKernelTrace, cpuName);\r
-                    try {\r
-                        int currentThreadQuark = ssq.getQuarkRelative(cpuQuark, Attributes.CURRENT_THREAD);\r
-                        long resolution = (end - start) / fDisplayWidth;\r
-                        List<ITmfStateInterval> currentThreadIntervals = ssq.queryHistoryRange(currentThreadQuark, start, end, resolution);\r
-                        for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) {\r
-                            if (!currentThreadInterval.getStateValue().isNull() && currentThreadInterval.getStateValue().getType() == 0) {\r
-                                int currentThread = currentThreadInterval.getStateValue().unboxInt();\r
-                                long startTime = currentThreadInterval.getStartTime();\r
-                                long endTime = currentThreadInterval.getEndTime();\r
-                                entry.addTraceEvent(new TimeEvent(entry, startTime, endTime - startTime));\r
-                            }\r
-                        }\r
-                    } catch (AttributeNotFoundException e) {\r
-                        e.printStackTrace();\r
-                    } catch (TimeRangeException e) {\r
-                        e.printStackTrace();\r
-                    } catch (StateValueTypeException e) {\r
-                        e.printStackTrace();\r
-                    }\r
-                    groupEntry.addChild(entry);\r
-                    refresh();\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    private void refresh() {\r
-        Display.getDefault().asyncExec(new Runnable() {\r
-            @Override\r
-            public void run() {\r
-                if (fTimeGraphViewer.getControl().isDisposed()) {\r
-                    return;\r
-                }\r
-                fTimeGraphViewer.setInput(fEntryList.toArray(new ITimeGraphEntry[0]));\r
-                fTimeGraphViewer.setTimeBounds(fStartTime, fEndTime);\r
-                fTimeGraphViewer.setStartFinishTime(fStartTime, fEndTime);\r
-            }\r
-        });\r
-    }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2012 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes;
+import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Messages;
+import org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources.ResourcesEntry.Type;
+import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace;
+import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
+import org.eclipse.linuxtools.tmf.core.exceptions.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.signal.TmfRangeSynchSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
+import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
+import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
+import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
+import org.eclipse.linuxtools.tmf.ui.editors.ITmfTraceEditor;
+import org.eclipse.linuxtools.tmf.ui.views.TmfView;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphViewer;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * Main implementation for the LTTng 2.0 kernel Resource view
+ *
+ * @author Patrick Tasse
+ */
+public class ResourcesView extends TmfView {
+
+    // ------------------------------------------------------------------------
+    // Constants
+    // ------------------------------------------------------------------------
+
+    /** View ID. */
+    public static final String ID = "org.eclipse.linuxtools.lttng2.kernel.ui.views.resources"; //$NON-NLS-1$
+
+    /**
+     * Redraw state enum
+     */
+    private enum State { IDLE, BUSY, PENDING }
+
+    // ------------------------------------------------------------------------
+    // Fields
+    // ------------------------------------------------------------------------
+
+    // The time graph viewer
+    TimeGraphViewer fTimeGraphViewer;
+
+    // The selected trace
+    private ITmfTrace fTrace;
+
+    // The time graph entry list
+    private ArrayList<TraceEntry> fEntryList;
+
+    // The trace to entry list hash map
+    final private HashMap<ITmfTrace, ArrayList<TraceEntry>> fEntryListMap = new HashMap<ITmfTrace, ArrayList<TraceEntry>>();
+
+    // The trace to build thread hash map
+    final private HashMap<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<ITmfTrace, BuildThread>();
+
+    // The start time
+    private long fStartTime;
+
+    // The end time
+    private long fEndTime;
+
+    // The display width
+    private final int fDisplayWidth;
+
+    // The next resource action
+    private Action fNextResourceAction;
+
+    // The previous resource action
+    private Action fPreviousResourceAction;
+
+    // The zoom thread
+    private ZoomThread fZoomThread;
+
+    // The redraw state used to prevent unnecessary queuing of display runnables
+    private State fRedrawState = State.IDLE;
+
+    // The redraw synchronization object
+    final private Object fSyncObj = new Object();
+
+    // ------------------------------------------------------------------------
+    // Classes
+    // ------------------------------------------------------------------------
+
+    private class TraceEntry implements ITimeGraphEntry {
+        // The Trace
+        private final CtfKernelTrace fKernelTrace;
+        // The start time
+        private final long fTraceStartTime;
+        // The end time
+        private final long fTraceEndTime;
+        // The children of the entry
+        private final ArrayList<ResourcesEntry> fChildren;
+        // The name of entry
+        private final String fName;
+
+        public TraceEntry(CtfKernelTrace trace, String name, long startTime, long endTime) {
+            fKernelTrace = trace;
+            fChildren = new ArrayList<ResourcesEntry>();
+            fName = name;
+            fTraceStartTime = startTime;
+            fTraceEndTime = endTime;
+        }
+
+        @Override
+        public ITimeGraphEntry getParent() {
+            return null;
+        }
+
+        @Override
+        public boolean hasChildren() {
+            return fChildren != null && fChildren.size() > 0;
+        }
+
+        @Override
+        public List<ResourcesEntry> getChildren() {
+            return fChildren;
+        }
+
+        @Override
+        public String getName() {
+            return fName;
+        }
+
+        @Override
+        public long getStartTime() {
+            return fTraceStartTime;
+        }
+
+        @Override
+        public long getEndTime() {
+            return fTraceEndTime;
+        }
+
+        @Override
+        public boolean hasTimeEvents() {
+            return false;
+        }
+
+        @Override
+        public Iterator<ITimeEvent> getTimeEventsIterator() {
+            return null;
+        }
+
+        @Override
+        public <T extends ITimeEvent> Iterator<T> getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) {
+            return null;
+        }
+
+        public CtfKernelTrace getTrace() {
+            return fKernelTrace;
+        }
+
+        public void addChild(ResourcesEntry entry) {
+            int index;
+            for (index = 0; index < fChildren.size(); index++) {
+                ResourcesEntry other = fChildren.get(index);
+                if (entry.getType().compareTo(other.getType()) < 0) {
+                    break;
+                } else if (entry.getType().equals(other.getType())) {
+                    if (entry.getId() < other.getId()) {
+                        break;
+                    }
+                }
+            }
+            entry.setParent(this);
+            fChildren.add(index, entry);
+        }
+    }
+
+    private static class TraceEntryComparator implements Comparator<ITimeGraphEntry> {
+        @Override
+        public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
+            int result = o1.getStartTime() < o2.getStartTime() ? -1 : o1.getStartTime() > o2.getStartTime() ? 1 : 0;
+            if (result == 0) {
+                result = o1.getName().compareTo(o2.getName());
+            }
+            return result;
+        }
+    }
+
+    private class BuildThread extends Thread {
+        private final ITmfTrace fBuildTrace;
+        private final IProgressMonitor fMonitor;
+
+        public BuildThread(ITmfTrace trace) {
+            super("ResourcesView build"); //$NON-NLS-1$
+            fBuildTrace = trace;
+            fMonitor = new NullProgressMonitor();
+        }
+
+        @Override
+        public void run() {
+            buildEventList(fBuildTrace, fMonitor);
+            synchronized (fBuildThreadMap) {
+                fBuildThreadMap.remove(this);
+            }
+        }
+
+        public void cancel() {
+            fMonitor.setCanceled(true);
+        }
+    }
+
+    private class ZoomThread extends Thread {
+        private final ArrayList<TraceEntry> fZoomEntryList;
+        private final long fZoomStartTime;
+        private final long fZoomEndTime;
+        private final IProgressMonitor fMonitor;
+
+        public ZoomThread(ArrayList<TraceEntry> entryList, long startTime, long endTime) {
+            super("ResourcesView zoom"); //$NON-NLS-1$
+            fZoomEntryList = entryList;
+            fZoomStartTime = startTime;
+            fZoomEndTime = endTime;
+            fMonitor = new NullProgressMonitor();
+        }
+
+        @Override
+        public void run() {
+            if (fZoomEntryList == null) {
+                return;
+            }
+            long resolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
+            for (TraceEntry traceEntry : fZoomEntryList) {
+                if (!traceEntry.fKernelTrace.getStateSystem(CtfKernelTrace.STATE_ID).waitUntilBuilt()) {
+                    return;
+                }
+                for (ITimeGraphEntry child : traceEntry.getChildren()) {
+                    if (fMonitor.isCanceled()) {
+                        break;
+                    }
+                    ResourcesEntry entry = (ResourcesEntry) child;
+                    if (fZoomStartTime <= fStartTime && fZoomEndTime >= fEndTime) {
+                        entry.setZoomedEventList(null);
+                    } else {
+                        List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, resolution, true, fMonitor);
+                        if (zoomedEventList != null) {
+                            entry.setZoomedEventList(zoomedEventList);
+                        }
+                    }
+                    redraw();
+                }
+            }
+        }
+
+        public void cancel() {
+            fMonitor.setCanceled(true);
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+    /**
+     * Default constructor
+     */
+    public ResourcesView() {
+        super(ID);
+        fDisplayWidth = Display.getDefault().getBounds().width;
+    }
+
+    // ------------------------------------------------------------------------
+    // ViewPart
+    // ------------------------------------------------------------------------
+
+    /* (non-Javadoc)
+     * @see org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse.swt.widgets.Composite)
+     */
+    @Override
+    public void createPartControl(Composite parent) {
+        fTimeGraphViewer = new TimeGraphViewer(parent, SWT.NONE);
+
+        fTimeGraphViewer.setTimeGraphProvider(new ResourcesPresentationProvider(fTimeGraphViewer));
+
+        fTimeGraphViewer.setTimeFormat(TimeFormat.CALENDAR);
+
+        fTimeGraphViewer.addRangeListener(new ITimeGraphRangeListener() {
+            @Override
+            public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
+                long startTime = event.getStartTime();
+                long endTime = event.getEndTime();
+                TmfTimeRange range = new TmfTimeRange(new CtfTmfTimestamp(startTime), new CtfTmfTimestamp(endTime));
+                TmfTimestamp time = new CtfTmfTimestamp(fTimeGraphViewer.getSelectedTime());
+                broadcast(new TmfRangeSynchSignal(ResourcesView.this, range, time));
+                startZoomThread(startTime, endTime);
+            }
+        });
+
+        fTimeGraphViewer.addTimeListener(new ITimeGraphTimeListener() {
+            @Override
+            public void timeSelected(TimeGraphTimeEvent event) {
+                long time = event.getTime();
+                broadcast(new TmfTimeSynchSignal(ResourcesView.this, new CtfTmfTimestamp(time)));
+            }
+        });
+
+        // View Action Handling
+        makeActions();
+        contributeToActionBars();
+
+        IEditorPart editor = getSite().getPage().getActiveEditor();
+        if (editor instanceof ITmfTraceEditor) {
+            ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
+            if (trace != null) {
+                traceSelected(new TmfTraceSelectedSignal(this, trace));
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
+     */
+    @Override
+    public void setFocus() {
+        fTimeGraphViewer.setFocus();
+    }
+
+    // ------------------------------------------------------------------------
+    // Signal handlers
+    // ------------------------------------------------------------------------
+
+    /**
+     * Handler for the trace selected signal
+     *
+     * @param signal
+     *            The incoming signal
+     */
+    @TmfSignalHandler
+    public void traceSelected(final TmfTraceSelectedSignal signal) {
+        if (signal.getTrace() == fTrace) {
+            return;
+        }
+        fTrace = signal.getTrace();
+
+        synchronized (fEntryListMap) {
+            fEntryList = fEntryListMap.get(fTrace);
+            if (fEntryList == null) {
+                synchronized (fBuildThreadMap) {
+                    BuildThread buildThread = new BuildThread(fTrace);
+                    fBuildThreadMap.put(fTrace, buildThread);
+                    buildThread.start();
+                }
+            } else {
+                fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+                fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+                refresh();
+            }
+        }
+    }
+
+    /**
+     * Trace is disposed: clear the data structures and the view
+     *
+     * @param signal the signal received
+     */
+    @TmfSignalHandler
+    public void traceClosed(final TmfTraceClosedSignal signal) {
+        synchronized (fBuildThreadMap) {
+            BuildThread buildThread = fBuildThreadMap.remove(signal.getTrace());
+            if (buildThread != null) {
+                buildThread.cancel();
+            }
+        }
+        synchronized (fEntryListMap) {
+            fEntryListMap.remove(signal.getTrace());
+        }
+        if (signal.getTrace() == fTrace) {
+            fTrace = null;
+            fStartTime = 0;
+            fEndTime = 0;
+            if (fZoomThread != null) {
+                fZoomThread.cancel();
+            }
+            refresh();
+        }
+    }
+
+    /**
+     * Handler for the TimeSynch signal
+     *
+     * @param signal
+     *            The incoming signal
+     */
+    @TmfSignalHandler
+    public void synchToTime(final TmfTimeSynchSignal signal) {
+        if (signal.getSource() == this || fTrace == null) {
+            return;
+        }
+        final long time = signal.getCurrentTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                if (fTimeGraphViewer.getControl().isDisposed()) {
+                    return;
+                }
+                fTimeGraphViewer.setSelectedTime(time, true);
+                startZoomThread(fTimeGraphViewer.getTime0(), fTimeGraphViewer.getTime1());
+            }
+        });
+    }
+
+    /**
+     * Handler for the RangeSynch signal
+     *
+     * @param signal
+     *            The incoming signal
+     */
+    @TmfSignalHandler
+    public void synchToRange(final TmfRangeSynchSignal signal) {
+        if (signal.getSource() == this || fTrace == null) {
+            return;
+        }
+        if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
+            return;
+        }
+        final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+        final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+        final long time = signal.getCurrentTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                if (fTimeGraphViewer.getControl().isDisposed()) {
+                    return;
+                }
+                fTimeGraphViewer.setStartFinishTime(startTime, endTime);
+                fTimeGraphViewer.setSelectedTime(time, false);
+                startZoomThread(startTime, endTime);
+            }
+        });
+    }
+
+    // ------------------------------------------------------------------------
+    // Internal
+    // ------------------------------------------------------------------------
+
+    private void buildEventList(final ITmfTrace trace, IProgressMonitor monitor) {
+        fStartTime = Long.MAX_VALUE;
+        fEndTime = Long.MIN_VALUE;
+        ITmfTrace[] traces;
+        if (trace instanceof TmfExperiment) {
+            TmfExperiment experiment = (TmfExperiment) trace;
+            traces = experiment.getTraces();
+        } else {
+            traces = new ITmfTrace[] { trace };
+        }
+        ArrayList<TraceEntry> entryList = new ArrayList<TraceEntry>();
+        for (ITmfTrace aTrace : traces) {
+            if (monitor.isCanceled()) {
+                return;
+            }
+            if (aTrace instanceof CtfKernelTrace) {
+                CtfKernelTrace ctfKernelTrace = (CtfKernelTrace) aTrace;
+                ITmfStateSystem ssq = ctfKernelTrace.getStateSystem(CtfKernelTrace.STATE_ID);
+                if (!ssq.waitUntilBuilt()) {
+                    return;
+                }
+                long startTime = ssq.getStartTime();
+                long endTime = ssq.getCurrentEndTime() + 1;
+                TraceEntry groupEntry = new TraceEntry(ctfKernelTrace, aTrace.getName(), startTime, endTime);
+                entryList.add(groupEntry);
+                fStartTime = Math.min(fStartTime, startTime);
+                fEndTime = Math.max(fEndTime, endTime);
+                List<Integer> cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$
+                ResourcesEntry[] cpuEntries = new ResourcesEntry[cpuQuarks.size()];
+                for (int i = 0; i < cpuQuarks.size(); i++) {
+                    int cpuQuark = cpuQuarks.get(i);
+                    int cpu = Integer.parseInt(ssq.getAttributeName(cpuQuark));
+                    ResourcesEntry entry = new ResourcesEntry(cpuQuark, ctfKernelTrace, Type.CPU, cpu);
+                    groupEntry.addChild(entry);
+                    cpuEntries[i] = entry;
+                }
+                List<Integer> irqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.IRQS, "*"); //$NON-NLS-1$
+                ResourcesEntry[] irqEntries = new ResourcesEntry[irqQuarks.size()];
+                for (int i = 0; i < irqQuarks.size(); i++) {
+                    int irqQuark = irqQuarks.get(i);
+                    int irq = Integer.parseInt(ssq.getAttributeName(irqQuark));
+                    ResourcesEntry entry = new ResourcesEntry(irqQuark, ctfKernelTrace, Type.IRQ, irq);
+                    groupEntry.addChild(entry);
+                    irqEntries[i] = entry;
+                }
+                List<Integer> softIrqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$
+                ResourcesEntry[] softIrqEntries = new ResourcesEntry[softIrqQuarks.size()];
+                for (int i = 0; i < softIrqQuarks.size(); i++) {
+                    int softIrqQuark = softIrqQuarks.get(i);
+                    int softIrq = Integer.parseInt(ssq.getAttributeName(softIrqQuark));
+                    ResourcesEntry entry = new ResourcesEntry(softIrqQuark, ctfKernelTrace, Type.SOFT_IRQ, softIrq);
+                    groupEntry.addChild(entry);
+                    softIrqEntries[i] = entry;
+                }
+            }
+        }
+        synchronized (fEntryListMap) {
+            fEntryListMap.put(trace, (ArrayList<TraceEntry>) entryList.clone());
+        }
+        if (trace == fTrace) {
+            refresh();
+        }
+        for (TraceEntry traceEntry : entryList) {
+            if (monitor.isCanceled()) {
+                return;
+            }
+            CtfKernelTrace ctfKernelTrace = traceEntry.getTrace();
+            ITmfStateSystem ssq = ctfKernelTrace.getStateSystem(CtfKernelTrace.STATE_ID);
+            long startTime = ssq.getStartTime();
+            long endTime = ssq.getCurrentEndTime() + 1;
+            long resolution = (endTime - startTime) / fDisplayWidth;
+            for (ResourcesEntry entry : traceEntry.getChildren()) {
+                List<ITimeEvent> eventList = getEventList(entry, startTime, endTime, resolution, false, monitor);
+                entry.setEventList(eventList);
+                redraw();
+            }
+        }
+    }
+
+    private static List<ITimeEvent> getEventList(ResourcesEntry entry,
+            long startTime, long endTime, long resolution, boolean includeNull,
+            IProgressMonitor monitor) {
+        ITmfStateSystem ssq = entry.getTrace().getStateSystem(CtfKernelTrace.STATE_ID);
+        startTime = Math.max(startTime, ssq.getStartTime());
+        endTime = Math.min(endTime, ssq.getCurrentEndTime() + 1);
+        if (endTime <= startTime) {
+            return null;
+        }
+        List<ITimeEvent> eventList = null;
+        int quark = entry.getQuark();
+        try {
+            if (entry.getType().equals(Type.CPU)) {
+                int statusQuark = ssq.getQuarkRelative(quark, Attributes.STATUS);
+                List<ITmfStateInterval> statusIntervals = ssq.queryHistoryRange(statusQuark, startTime, endTime - 1, resolution, monitor);
+                eventList = new ArrayList<ITimeEvent>(statusIntervals.size());
+                long lastEndTime = -1;
+                for (ITmfStateInterval statusInterval : statusIntervals) {
+                    if (monitor.isCanceled()) {
+                        return null;
+                    }
+                    int status = statusInterval.getStateValue().unboxInt();
+                    long time = statusInterval.getStartTime();
+                    long duration = statusInterval.getEndTime() - time + 1;
+                    if (!statusInterval.getStateValue().isNull()) {
+                        if (lastEndTime != time && lastEndTime != -1) {
+                            eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
+                        }
+                        eventList.add(new ResourcesEvent(entry, time, duration, status));
+                        lastEndTime = time + duration;
+                    } else {
+                        if (includeNull) {
+                            eventList.add(new ResourcesEvent(entry, time, duration));
+                        }
+                    }
+                }
+            } else if (entry.getType().equals(Type.IRQ)) {
+                List<ITmfStateInterval> irqIntervals = ssq.queryHistoryRange(quark, startTime, endTime - 1, resolution, monitor);
+                eventList = new ArrayList<ITimeEvent>(irqIntervals.size());
+                long lastEndTime = -1;
+                boolean lastIsNull = true;
+                for (ITmfStateInterval irqInterval : irqIntervals) {
+                    if (monitor.isCanceled()) {
+                        return null;
+                    }
+                    long time = irqInterval.getStartTime();
+                    long duration = irqInterval.getEndTime() - time + 1;
+                    if (!irqInterval.getStateValue().isNull()) {
+                        int cpu = irqInterval.getStateValue().unboxInt();
+                        eventList.add(new ResourcesEvent(entry, time, duration, cpu));
+                        lastIsNull = false;
+                    } else {
+                        if (lastEndTime != time && lastEndTime != -1 && lastIsNull) {
+                            eventList.add(new ResourcesEvent(entry, lastEndTime, time - lastEndTime, -1));
+                        }
+                        if (includeNull) {
+                            eventList.add(new ResourcesEvent(entry, time, duration));
+                        }
+                        lastIsNull = true;
+                    }
+                    lastEndTime = time + duration;
+                }
+            } else if (entry.getType().equals(Type.SOFT_IRQ)) {
+                List<ITmfStateInterval> softIrqIntervals = ssq.queryHistoryRange(quark, startTime, endTime - 1, resolution, monitor);
+                eventList = new ArrayList<ITimeEvent>(softIrqIntervals.size());
+                long lastEndTime = -1;
+                boolean lastIsNull = true;
+                for (ITmfStateInterval softIrqInterval : softIrqIntervals) {
+                    if (monitor.isCanceled()) {
+                        return null;
+                    }
+                    long time = softIrqInterval.getStartTime();
+                    long duration = softIrqInterval.getEndTime() - time + 1;
+                    if (!softIrqInterval.getStateValue().isNull()) {
+                        int cpu = softIrqInterval.getStateValue().unboxInt();
+                        eventList.add(new ResourcesEvent(entry, time, duration, cpu));
+                    } else {
+                        if (lastEndTime != time && lastEndTime != -1 && lastIsNull) {
+                            eventList.add(new ResourcesEvent(entry, lastEndTime, time - lastEndTime, -1));
+                        }
+                        if (includeNull) {
+                            eventList.add(new ResourcesEvent(entry, time, duration));
+                        }
+                        lastIsNull = true;
+                    }
+                    lastEndTime = time + duration;
+                }
+            }
+        } catch (AttributeNotFoundException e) {
+            e.printStackTrace();
+        } catch (TimeRangeException e) {
+            e.printStackTrace();
+        } catch (StateValueTypeException e) {
+            e.printStackTrace();
+        } catch (StateSystemDisposedException e) {
+            /* Ignored */
+        }
+        return eventList;
+    }
+
+    private void refresh() {
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                if (fTimeGraphViewer.getControl().isDisposed()) {
+                    return;
+                }
+                ITimeGraphEntry[] entries = null;
+                synchronized (fEntryListMap) {
+                    fEntryList = fEntryListMap.get(fTrace);
+                    if (fEntryList == null) {
+                        fEntryList = new ArrayList<TraceEntry>();
+                    }
+                    entries = fEntryList.toArray(new ITimeGraphEntry[0]);
+                }
+                if (entries != null) {
+                    Arrays.sort(entries, new TraceEntryComparator());
+                    fTimeGraphViewer.setInput(entries);
+                    fTimeGraphViewer.setTimeBounds(fStartTime, fEndTime);
+
+                    long timestamp = fTrace == null ? 0 : fTrace.getCurrentTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+                    long startTime = fTrace == null ? 0 : fTrace.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+                    long endTime = fTrace == null ? 0 : fTrace.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+                    startTime = Math.max(startTime, fStartTime);
+                    endTime = Math.min(endTime, fEndTime);
+                    fTimeGraphViewer.setSelectedTime(timestamp, false);
+                    fTimeGraphViewer.setStartFinishTime(startTime, endTime);
+
+                    startZoomThread(startTime, endTime);
+                }
+            }
+        });
+    }
+
+    private void redraw() {
+        synchronized (fSyncObj) {
+            if (fRedrawState == State.IDLE) {
+                fRedrawState = State.BUSY;
+            } else {
+                fRedrawState = State.PENDING;
+                return;
+            }
+        }
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                if (fTimeGraphViewer.getControl().isDisposed()) {
+                    return;
+                }
+                fTimeGraphViewer.getControl().redraw();
+                fTimeGraphViewer.getControl().update();
+                synchronized (fSyncObj) {
+                    if (fRedrawState == State.PENDING) {
+                        fRedrawState = State.IDLE;
+                        redraw();
+                    } else {
+                        fRedrawState = State.IDLE;
+                    }
+                }
+            }
+        });
+    }
+
+    private void startZoomThread(long startTime, long endTime) {
+        if (fZoomThread != null) {
+            fZoomThread.cancel();
+        }
+        fZoomThread = new ZoomThread(fEntryList, startTime, endTime);
+        fZoomThread.start();
+    }
+
+    private void makeActions() {
+        fPreviousResourceAction = fTimeGraphViewer.getPreviousItemAction();
+        fPreviousResourceAction.setText(Messages.ResourcesView_previousResourceActionNameText);
+        fPreviousResourceAction.setToolTipText(Messages.ResourcesView_previousResourceActionToolTipText);
+        fNextResourceAction = fTimeGraphViewer.getNextItemAction();
+        fNextResourceAction.setText(Messages.ResourcesView_nextResourceActionNameText);
+        fNextResourceAction.setToolTipText(Messages.ResourcesView_previousResourceActionToolTipText);
+    }
+
+    private void contributeToActionBars() {
+        IActionBars bars = getViewSite().getActionBars();
+        fillLocalToolBar(bars.getToolBarManager());
+    }
+
+    private void fillLocalToolBar(IToolBarManager manager) {
+        manager.add(fTimeGraphViewer.getShowLegendAction());
+        manager.add(new Separator());
+        manager.add(fTimeGraphViewer.getResetScaleAction());
+        manager.add(fTimeGraphViewer.getPreviousEventAction());
+        manager.add(fTimeGraphViewer.getNextEventAction());
+        manager.add(fPreviousResourceAction);
+        manager.add(fNextResourceAction);
+        manager.add(fTimeGraphViewer.getZoomInAction());
+        manager.add(fTimeGraphViewer.getZoomOutAction());
+        manager.add(new Separator());
+    }
+}
This page took 0.032806 seconds and 5 git commands to generate.