07867a0d55f7c37843b883bf021b5f6ef7a86ac9
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.kernel.ui / src / org / eclipse / linuxtools / internal / lttng2 / kernel / ui / views / controlflow / ControlFlowView.java
1 /*******************************************************************************
2 * Copyright (c) 2012 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Patrick Tasse - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.controlflow;
14
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.Comparator;
19 import java.util.HashMap;
20 import java.util.List;
21
22 import org.eclipse.core.runtime.IProgressMonitor;
23 import org.eclipse.core.runtime.NullProgressMonitor;
24 import org.eclipse.jface.action.Action;
25 import org.eclipse.jface.action.IToolBarManager;
26 import org.eclipse.jface.action.Separator;
27 import org.eclipse.jface.viewers.ILabelProviderListener;
28 import org.eclipse.jface.viewers.ITableLabelProvider;
29 import org.eclipse.jface.viewers.ITreeContentProvider;
30 import org.eclipse.jface.viewers.Viewer;
31 import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes;
32 import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Messages;
33 import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace;
34 import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTimestamp;
35 import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
36 import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
37 import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
38 import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
39 import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
40 import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
41 import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
42 import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
43 import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
44 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
45 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
46 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
47 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
48 import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
49 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
50 import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
51 import org.eclipse.linuxtools.tmf.ui.editors.ITmfTraceEditor;
52 import org.eclipse.linuxtools.tmf.ui.views.TmfView;
53 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
54 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;
55 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
56 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphCombo;
57 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
58 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphSelectionEvent;
59 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
60 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
61 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
62 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent;
63 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils;
64 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
65 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
66 import org.eclipse.swt.SWT;
67 import org.eclipse.swt.graphics.Image;
68 import org.eclipse.swt.widgets.Composite;
69 import org.eclipse.swt.widgets.Display;
70 import org.eclipse.swt.widgets.TreeColumn;
71 import org.eclipse.ui.IActionBars;
72 import org.eclipse.ui.IEditorPart;
73
74 /**
75 * The Control Flow view main object
76 *
77 */
78 public class ControlFlowView extends TmfView {
79
80 // ------------------------------------------------------------------------
81 // Constants
82 // ------------------------------------------------------------------------
83
84 /**
85 * View ID.
86 */
87 public static final String ID = "org.eclipse.linuxtools.lttng2.kernel.ui.views.controlflow"; //$NON-NLS-1$
88
89 private static final String PROCESS_COLUMN = Messages.ControlFlowView_processColumn;
90 private static final String TID_COLUMN = Messages.ControlFlowView_tidColumn;
91 private static final String PTID_COLUMN = Messages.ControlFlowView_ptidColumn;
92 private static final String BIRTH_TIME_COLUMN = Messages.ControlFlowView_birthTimeColumn;
93 private static final String TRACE_COLUMN = Messages.ControlFlowView_traceColumn;
94
95 private final String[] COLUMN_NAMES = new String[] {
96 PROCESS_COLUMN,
97 TID_COLUMN,
98 PTID_COLUMN,
99 BIRTH_TIME_COLUMN,
100 TRACE_COLUMN
101 };
102
103 /**
104 * Redraw state enum
105 */
106 private enum State { IDLE, BUSY, PENDING }
107
108 // ------------------------------------------------------------------------
109 // Fields
110 // ------------------------------------------------------------------------
111
112 // The timegraph combo
113 private TimeGraphCombo fTimeGraphCombo;
114
115 // The selected trace
116 private ITmfTrace fTrace;
117
118 // The timegraph entry list
119 private ArrayList<ControlFlowEntry> fEntryList;
120
121 // The trace to entry list hash map
122 final private HashMap<ITmfTrace, ArrayList<ControlFlowEntry>> fEntryListMap = new HashMap<ITmfTrace, ArrayList<ControlFlowEntry>>();
123
124 // The trace to build thread hash map
125 final private HashMap<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<ITmfTrace, BuildThread>();
126
127 // The start time
128 private long fStartTime;
129
130 // The end time
131 private long fEndTime;
132
133 // The display width
134 private final int fDisplayWidth;
135
136 // The zoom thread
137 private ZoomThread fZoomThread;
138
139 // The next resource action
140 private Action fNextResourceAction;
141
142 // The previous resource action
143 private Action fPreviousResourceAction;
144
145 // A comparator class
146 private final ControlFlowEntryComparator fControlFlowEntryComparator = new ControlFlowEntryComparator();
147
148 // The redraw state used to prevent unnecessary queuing of display runnables
149 private State fRedrawState = State.IDLE;
150
151 // The redraw synchronization object
152 final private Object fSyncObj = new Object();
153
154 // ------------------------------------------------------------------------
155 // Classes
156 // ------------------------------------------------------------------------
157
158 private class TreeContentProvider implements ITreeContentProvider {
159
160 @Override
161 public void dispose() {
162 }
163
164 @Override
165 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
166 }
167
168 @Override
169 public Object[] getElements(Object inputElement) {
170 return (ITimeGraphEntry[]) inputElement;
171 }
172
173 @Override
174 public Object[] getChildren(Object parentElement) {
175 ITimeGraphEntry entry = (ITimeGraphEntry) parentElement;
176 List<? extends ITimeGraphEntry> children = entry.getChildren();
177 return children.toArray(new ITimeGraphEntry[children.size()]);
178 }
179
180 @Override
181 public Object getParent(Object element) {
182 ITimeGraphEntry entry = (ITimeGraphEntry) element;
183 return entry.getParent();
184 }
185
186 @Override
187 public boolean hasChildren(Object element) {
188 ITimeGraphEntry entry = (ITimeGraphEntry) element;
189 return entry.hasChildren();
190 }
191
192 }
193
194 private class TreeLabelProvider implements ITableLabelProvider {
195
196 @Override
197 public void addListener(ILabelProviderListener listener) {
198 }
199
200 @Override
201 public void dispose() {
202 }
203
204 @Override
205 public boolean isLabelProperty(Object element, String property) {
206 return false;
207 }
208
209 @Override
210 public void removeListener(ILabelProviderListener listener) {
211 }
212
213 @Override
214 public Image getColumnImage(Object element, int columnIndex) {
215 return null;
216 }
217
218 @Override
219 public String getColumnText(Object element, int columnIndex) {
220 ControlFlowEntry entry = (ControlFlowEntry) element;
221 if (columnIndex == 0) {
222 return entry.getName();
223 } else if (columnIndex == 1) {
224 return Integer.toString(entry.getThreadId());
225 } else if (columnIndex == 2) {
226 if (entry.getParentThreadId() > 0) {
227 return Integer.toString(entry.getParentThreadId());
228 }
229 } else if (columnIndex == 3) {
230 return Utils.formatTime(entry.getBirthTime(), TimeFormat.ABSOLUTE, Resolution.NANOSEC);
231 } else if (columnIndex == 4) {
232 return entry.getTrace().getName();
233 }
234 return ""; //$NON-NLS-1$
235 }
236
237 }
238
239 private static class ControlFlowEntryComparator implements Comparator<ITimeGraphEntry> {
240
241 @Override
242 public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
243 int result = 0;
244
245 if ((o1 instanceof ControlFlowEntry) && (o2 instanceof ControlFlowEntry)) {
246 ControlFlowEntry entry1 = (ControlFlowEntry) o1;
247 ControlFlowEntry entry2 = (ControlFlowEntry) o2;
248 result = entry1.getTrace().getStartTime().compareTo(entry2.getTrace().getStartTime());
249 if (result == 0) {
250 result = entry1.getTrace().getName().compareTo(entry2.getTrace().getName());
251 }
252 if (result == 0) {
253 result = entry1.getThreadId() < entry2.getThreadId() ? -1 : entry1.getThreadId() > entry2.getThreadId() ? 1 : 0;
254 }
255 }
256
257 if (result == 0) {
258 result = o1.getStartTime() < o2.getStartTime() ? -1 : o1.getStartTime() > o2.getStartTime() ? 1 : 0;
259 }
260
261 return result;
262 }
263 }
264
265 private class BuildThread extends Thread {
266 private final ITmfTrace fBuildTrace;
267 private final IProgressMonitor fMonitor;
268
269 public BuildThread(ITmfTrace trace) {
270 super("ControlFlowView build"); //$NON-NLS-1$
271 fBuildTrace = trace;
272 fMonitor = new NullProgressMonitor();
273 }
274
275 @Override
276 public void run() {
277 buildEventList(fBuildTrace, fMonitor);
278 synchronized (fBuildThreadMap) {
279 fBuildThreadMap.remove(this);
280 }
281 }
282
283 public void cancel() {
284 fMonitor.setCanceled(true);
285 }
286 }
287
288 private class ZoomThread extends Thread {
289 private final ArrayList<ControlFlowEntry> fZoomEntryList;
290 private final long fZoomStartTime;
291 private final long fZoomEndTime;
292 private final long fResolution;
293 private final IProgressMonitor fMonitor;
294
295 public ZoomThread(ArrayList<ControlFlowEntry> entryList, long startTime, long endTime) {
296 super("ControlFlowView zoom"); //$NON-NLS-1$
297 fZoomEntryList = entryList;
298 fZoomStartTime = startTime;
299 fZoomEndTime = endTime;
300 fResolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
301 fMonitor = new NullProgressMonitor();
302 }
303
304 @Override
305 public void run() {
306 if (fZoomEntryList == null) {
307 return;
308 }
309 for (ControlFlowEntry entry : fZoomEntryList) {
310 if (fMonitor.isCanceled()) {
311 break;
312 }
313 zoom(entry, fMonitor);
314 }
315 }
316
317 private void zoom(ControlFlowEntry entry, IProgressMonitor monitor) {
318 if (fZoomStartTime <= fStartTime && fZoomEndTime >= fEndTime) {
319 entry.setZoomedEventList(null);
320 } else {
321 List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, fResolution, monitor);
322 if (zoomedEventList != null) {
323 entry.setZoomedEventList(zoomedEventList);
324 }
325 }
326 redraw();
327 for (ControlFlowEntry child : entry.getChildren()) {
328 if (fMonitor.isCanceled()) {
329 return;
330 }
331 zoom(child, monitor);
332 }
333 }
334
335 public void cancel() {
336 fMonitor.setCanceled(true);
337 }
338 }
339
340 // ------------------------------------------------------------------------
341 // Constructors
342 // ------------------------------------------------------------------------
343
344 /**
345 * Constructor
346 */
347 public ControlFlowView() {
348 super(ID);
349 fDisplayWidth = Display.getDefault().getBounds().width;
350 }
351
352 // ------------------------------------------------------------------------
353 // ViewPart
354 // ------------------------------------------------------------------------
355
356 /* (non-Javadoc)
357 * @see org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse.swt.widgets.Composite)
358 */
359 @Override
360 public void createPartControl(Composite parent) {
361 fTimeGraphCombo = new TimeGraphCombo(parent, SWT.NONE);
362
363 fTimeGraphCombo.setTreeContentProvider(new TreeContentProvider());
364
365 fTimeGraphCombo.setTreeLabelProvider(new TreeLabelProvider());
366
367 fTimeGraphCombo.setTimeGraphProvider(new ControlFlowPresentationProvider());
368
369 fTimeGraphCombo.setTreeColumns(COLUMN_NAMES);
370
371 fTimeGraphCombo.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
372 @Override
373 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
374 final long startTime = event.getStartTime();
375 final long endTime = event.getEndTime();
376 TmfTimeRange range = new TmfTimeRange(new CtfTmfTimestamp(startTime), new CtfTmfTimestamp(endTime));
377 TmfTimestamp time = new CtfTmfTimestamp(fTimeGraphCombo.getTimeGraphViewer().getSelectedTime());
378 broadcast(new TmfRangeSynchSignal(ControlFlowView.this, range, time));
379 if (fZoomThread != null) {
380 fZoomThread.cancel();
381 }
382 startZoomThread(startTime, endTime);
383 }
384 });
385
386 fTimeGraphCombo.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
387 @Override
388 public void timeSelected(TimeGraphTimeEvent event) {
389 long time = event.getTime();
390 broadcast(new TmfTimeSynchSignal(ControlFlowView.this, new CtfTmfTimestamp(time)));
391 }
392 });
393
394 fTimeGraphCombo.addSelectionListener(new ITimeGraphSelectionListener() {
395 @Override
396 public void selectionChanged(TimeGraphSelectionEvent event) {
397 //ITimeGraphEntry selection = event.getSelection();
398 }
399 });
400
401 fTimeGraphCombo.getTimeGraphViewer().setTimeCalendarFormat(true);
402
403 // View Action Handling
404 makeActions();
405 contributeToActionBars();
406
407 IEditorPart editor = getSite().getPage().getActiveEditor();
408 if (editor instanceof ITmfTraceEditor) {
409 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
410 if (trace != null) {
411 traceSelected(new TmfTraceSelectedSignal(this, trace));
412 }
413 }
414 }
415
416 /* (non-Javadoc)
417 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
418 */
419 @Override
420 public void setFocus() {
421 fTimeGraphCombo.setFocus();
422 }
423
424 // ------------------------------------------------------------------------
425 // Signal handlers
426 // ------------------------------------------------------------------------
427
428 /**
429 * Handler for the trace selected signal
430 *
431 * @param signal
432 * The signal that's received
433 */
434 @TmfSignalHandler
435 public void traceSelected(final TmfTraceSelectedSignal signal) {
436 if (signal.getTrace() == fTrace) {
437 return;
438 }
439 fTrace = signal.getTrace();
440
441 synchronized (fEntryListMap) {
442 fEntryList = fEntryListMap.get(fTrace);
443 if (fEntryList == null) {
444 synchronized (fBuildThreadMap) {
445 BuildThread buildThread = new BuildThread(fTrace);
446 fBuildThreadMap.put(fTrace, buildThread);
447 buildThread.start();
448 }
449 } else {
450 fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
451 fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
452 refresh();
453 }
454 }
455 }
456
457 /**
458 * Trace is closed: clear the data structures and the view
459 *
460 * @param signal the signal received
461 */
462 @TmfSignalHandler
463 public void traceClosed(final TmfTraceClosedSignal signal) {
464 synchronized (fBuildThreadMap) {
465 BuildThread buildThread = fBuildThreadMap.remove(signal.getTrace());
466 if (buildThread != null) {
467 buildThread.cancel();
468 }
469 }
470 synchronized (fEntryListMap) {
471 fEntryListMap.remove(signal.getTrace());
472 }
473 if (signal.getTrace() == fTrace) {
474 fTrace = null;
475 fStartTime = 0;
476 fEndTime = 0;
477 if (fZoomThread != null) {
478 fZoomThread.cancel();
479 }
480 refresh();
481 }
482 }
483
484 /**
485 * Handler for the synch signal
486 *
487 * @param signal
488 * The signal that's received
489 */
490 @TmfSignalHandler
491 public void synchToTime(final TmfTimeSynchSignal signal) {
492 if (signal.getSource() == this || fTrace == null) {
493 return;
494 }
495 final long time = signal.getCurrentTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
496
497 int thread = -1;
498 ITmfTrace[] traces;
499 if (fTrace instanceof TmfExperiment) {
500 TmfExperiment experiment = (TmfExperiment) fTrace;
501 traces = experiment.getTraces();
502 } else {
503 traces = new ITmfTrace[] { fTrace };
504 }
505 for (ITmfTrace trace : traces) {
506 if (thread > 0) {
507 break;
508 }
509 if (trace instanceof CtfKernelTrace) {
510 CtfKernelTrace ctfKernelTrace = (CtfKernelTrace) trace;
511 ITmfStateSystem ssq = ctfKernelTrace.getStateSystem();
512 if (time >= ssq.getStartTime() && time <= ssq.getCurrentEndTime()) {
513 List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
514 for (int currentThreadQuark : currentThreadQuarks) {
515 try {
516 ITmfStateInterval currentThreadInterval = ssq.querySingleState(time, currentThreadQuark);
517 int currentThread = currentThreadInterval.getStateValue().unboxInt();
518 if (currentThread > 0) {
519 int statusQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThread), Attributes.STATUS);
520 ITmfStateInterval statusInterval = ssq.querySingleState(time, statusQuark);
521 if (statusInterval.getStartTime() == time) {
522 thread = currentThread;
523 break;
524 }
525 }
526 } catch (AttributeNotFoundException e) {
527 e.printStackTrace();
528 } catch (TimeRangeException e) {
529 e.printStackTrace();
530 } catch (StateValueTypeException e) {
531 e.printStackTrace();
532 } catch (StateSystemDisposedException e) {
533 /* Ignored */
534 }
535 }
536 }
537 }
538 }
539 final int selectedThread = thread;
540
541 Display.getDefault().asyncExec(new Runnable() {
542 @Override
543 public void run() {
544 if (fTimeGraphCombo.isDisposed()) {
545 return;
546 }
547 fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(time, true);
548 startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1());
549
550 if (selectedThread > 0) {
551 for (Object element : fTimeGraphCombo.getTimeGraphViewer().getExpandedElements()) {
552 if (element instanceof ControlFlowEntry) {
553 ControlFlowEntry entry = (ControlFlowEntry) element;
554 if (entry.getThreadId() == selectedThread) {
555 fTimeGraphCombo.setSelection(entry);
556 break;
557 }
558 }
559 }
560 }
561 }
562 });
563 }
564
565 /**
566 * Handler for the range sync signal
567 *
568 * @param signal
569 * The signal that's received
570 */
571 @TmfSignalHandler
572 public void synchToRange(final TmfRangeSynchSignal signal) {
573 if (signal.getSource() == this || fTrace == null) {
574 return;
575 }
576 final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
577 final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
578 final long time = signal.getCurrentTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
579 Display.getDefault().asyncExec(new Runnable() {
580 @Override
581 public void run() {
582 if (fTimeGraphCombo.isDisposed()) {
583 return;
584 }
585 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
586 fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(time, false);
587 startZoomThread(startTime, endTime);
588 }
589 });
590 }
591
592 // ------------------------------------------------------------------------
593 // Internal
594 // ------------------------------------------------------------------------
595
596 private void buildEventList(final ITmfTrace trace, IProgressMonitor monitor) {
597 fStartTime = Long.MAX_VALUE;
598 fEndTime = Long.MIN_VALUE;
599 ITmfTrace[] traces;
600 if (trace instanceof TmfExperiment) {
601 TmfExperiment experiment = (TmfExperiment) trace;
602 traces = experiment.getTraces();
603 } else {
604 traces = new ITmfTrace[] { trace };
605 }
606 ArrayList<ControlFlowEntry> rootList = new ArrayList<ControlFlowEntry>();
607 for (ITmfTrace aTrace : traces) {
608 if (monitor.isCanceled()) {
609 return;
610 }
611 if (aTrace instanceof CtfKernelTrace) {
612 ArrayList<ControlFlowEntry> entryList = new ArrayList<ControlFlowEntry>();
613 CtfKernelTrace ctfKernelTrace = (CtfKernelTrace) aTrace;
614 ITmfStateSystem ssq = ctfKernelTrace.getStateSystem();
615 if (!ssq.waitUntilBuilt()) {
616 return;
617 }
618 long start = ssq.getStartTime();
619 long end = ssq.getCurrentEndTime() + 1;
620 fStartTime = Math.min(fStartTime, start);
621 fEndTime = Math.max(fEndTime, end);
622 List<Integer> threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$
623 for (int threadQuark : threadQuarks) {
624 if (monitor.isCanceled()) {
625 return;
626 }
627 String threadName = ssq.getAttributeName(threadQuark);
628 int threadId = -1;
629 try {
630 threadId = Integer.parseInt(threadName);
631 } catch (NumberFormatException e1) {
632 continue;
633 }
634 if (threadId == 0) { // ignore the swapper thread
635 continue;
636 }
637 int execNameQuark = -1;
638 try {
639 try {
640 execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME);
641 } catch (AttributeNotFoundException e) {
642 continue;
643 }
644 int ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID);
645 List<ITmfStateInterval> execNameIntervals = ssq.queryHistoryRange(execNameQuark, start, end - 1); // use monitor when available in api
646 if (monitor.isCanceled()) {
647 return;
648 }
649 long birthTime = -1;
650 for (ITmfStateInterval execNameInterval : execNameIntervals) {
651 if (monitor.isCanceled()) {
652 return;
653 }
654 if (!execNameInterval.getStateValue().isNull() && execNameInterval.getStateValue().getType() == 1) {
655 String execName = execNameInterval.getStateValue().unboxStr();
656 long startTime = execNameInterval.getStartTime();
657 long endTime = execNameInterval.getEndTime() + 1;
658 if (birthTime == -1) {
659 birthTime = startTime;
660 }
661 int ppid = -1;
662 if (ppidQuark != -1) {
663 ITmfStateInterval ppidInterval = ssq.querySingleState(startTime, ppidQuark);
664 ppid = ppidInterval.getStateValue().unboxInt();
665 }
666 ControlFlowEntry entry = new ControlFlowEntry(threadQuark, ctfKernelTrace, execName, threadId, ppid, birthTime, startTime, endTime);
667 entryList.add(entry);
668 entry.addEvent(new TimeEvent(entry, startTime, endTime - startTime));
669 } else {
670 birthTime = -1;
671 }
672 }
673 } catch (AttributeNotFoundException e) {
674 e.printStackTrace();
675 } catch (TimeRangeException e) {
676 e.printStackTrace();
677 } catch (StateValueTypeException e) {
678 e.printStackTrace();
679 } catch (StateSystemDisposedException e) {
680 /* Ignored */
681 }
682 }
683 buildTree(entryList, rootList);
684 }
685 Collections.sort(rootList, fControlFlowEntryComparator);
686 synchronized (fEntryListMap) {
687 fEntryListMap.put(trace, (ArrayList<ControlFlowEntry>) rootList.clone());
688 }
689 if (trace == fTrace) {
690 refresh();
691 }
692 }
693 for (ControlFlowEntry entry : rootList) {
694 if (monitor.isCanceled()) {
695 return;
696 }
697 buildStatusEvents(trace, entry, monitor);
698 }
699 }
700
701 private static void buildTree(ArrayList<ControlFlowEntry> entryList,
702 ArrayList<ControlFlowEntry> rootList) {
703 for (ControlFlowEntry entry : entryList) {
704 boolean root = true;
705 if (entry.getParentThreadId() > 0) {
706 for (ControlFlowEntry parent : entryList) {
707 if (parent.getThreadId() == entry.getParentThreadId() &&
708 entry.getStartTime() >= parent.getStartTime() &&
709 entry.getStartTime() <= parent.getEndTime()) {
710 parent.addChild(entry);
711 root = false;
712 break;
713 }
714 }
715 }
716 if (root) {
717 rootList.add(entry);
718 }
719 }
720 }
721
722 private void buildStatusEvents(ITmfTrace trace, ControlFlowEntry entry, IProgressMonitor monitor) {
723 ITmfStateSystem ssq = entry.getTrace().getStateSystem();
724 long start = ssq.getStartTime();
725 long end = ssq.getCurrentEndTime() + 1;
726 long resolution = Math.max(1, (end - start) / fDisplayWidth);
727 List<ITimeEvent> eventList = getEventList(entry, entry.getStartTime(), entry.getEndTime(), resolution, monitor);
728 if (monitor.isCanceled()) {
729 return;
730 }
731 entry.setEventList(eventList);
732 if (trace == fTrace) {
733 redraw();
734 }
735 for (ITimeGraphEntry child : entry.getChildren()) {
736 if (monitor.isCanceled()) {
737 return;
738 }
739 buildStatusEvents(trace, (ControlFlowEntry) child, monitor);
740 }
741 }
742
743 private static List<ITimeEvent> getEventList(ControlFlowEntry entry,
744 long startTime, long endTime, long resolution,
745 IProgressMonitor monitor) {
746 startTime = Math.max(startTime, entry.getStartTime());
747 endTime = Math.min(endTime, entry.getEndTime());
748 if (endTime <= startTime) {
749 return null;
750 }
751 ITmfStateSystem ssq = entry.getTrace().getStateSystem();
752 List<ITimeEvent> eventList = null;
753 try {
754 int statusQuark = ssq.getQuarkRelative(entry.getThreadQuark(), Attributes.STATUS);
755 List<ITmfStateInterval> statusIntervals = ssq.queryHistoryRange(statusQuark, startTime, endTime - 1, resolution, monitor);
756 eventList = new ArrayList<ITimeEvent>(statusIntervals.size());
757 long lastEndTime = -1;
758 for (ITmfStateInterval statusInterval : statusIntervals) {
759 if (monitor.isCanceled()) {
760 return null;
761 }
762 long time = statusInterval.getStartTime();
763 long duration = statusInterval.getEndTime() - time + 1;
764 int status = -1;
765 try {
766 status = statusInterval.getStateValue().unboxInt();
767 } catch (StateValueTypeException e) {
768 e.printStackTrace();
769 }
770 if (lastEndTime != time && lastEndTime != -1) {
771 eventList.add(new ControlFlowEvent(entry, lastEndTime, time - lastEndTime, 0));
772 }
773 eventList.add(new ControlFlowEvent(entry, time, duration, status));
774 lastEndTime = time + duration;
775 }
776 } catch (AttributeNotFoundException e) {
777 e.printStackTrace();
778 } catch (TimeRangeException e) {
779 e.printStackTrace();
780 } catch (StateSystemDisposedException e) {
781 /* Ignored */
782 }
783 return eventList;
784 }
785
786 private void refresh() {
787 Display.getDefault().asyncExec(new Runnable() {
788 @Override
789 public void run() {
790 if (fTimeGraphCombo.isDisposed()) {
791 return;
792 }
793 ITimeGraphEntry[] entries = null;
794 synchronized (fEntryListMap) {
795 fEntryList = fEntryListMap.get(fTrace);
796 if (fEntryList == null) {
797 fEntryList = new ArrayList<ControlFlowEntry>();
798 }
799 entries = fEntryList.toArray(new ITimeGraphEntry[0]);
800 }
801 Arrays.sort(entries, fControlFlowEntryComparator);
802 fTimeGraphCombo.setInput(entries);
803 fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);
804
805 long timestamp = fTrace == null ? 0 : fTrace.getCurrentTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
806 long startTime = fTrace == null ? 0 : fTrace.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
807 long endTime = fTrace == null ? 0 : fTrace.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
808 startTime = Math.max(startTime, fStartTime);
809 endTime = Math.min(endTime, fEndTime);
810 fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(timestamp, false);
811 fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
812
813 for (TreeColumn column : fTimeGraphCombo.getTreeViewer().getTree().getColumns()) {
814 column.pack();
815 }
816
817 startZoomThread(startTime, endTime);
818 }
819 });
820 }
821
822 private void redraw() {
823 synchronized (fSyncObj) {
824 if (fRedrawState == State.IDLE) {
825 fRedrawState = State.BUSY;
826 } else {
827 fRedrawState = State.PENDING;
828 return;
829 }
830 }
831 Display.getDefault().asyncExec(new Runnable() {
832 @Override
833 public void run() {
834 if (fTimeGraphCombo.isDisposed()) {
835 return;
836 }
837 fTimeGraphCombo.redraw();
838 fTimeGraphCombo.update();
839 synchronized (fSyncObj) {
840 if (fRedrawState == State.PENDING) {
841 fRedrawState = State.IDLE;
842 redraw();
843 } else {
844 fRedrawState = State.IDLE;
845 }
846 }
847 }
848 });
849 }
850
851 private void startZoomThread(long startTime, long endTime) {
852 if (fZoomThread != null) {
853 fZoomThread.cancel();
854 }
855 fZoomThread = new ZoomThread(fEntryList, startTime, endTime);
856 fZoomThread.start();
857 }
858
859 private void makeActions() {
860 fPreviousResourceAction = fTimeGraphCombo.getTimeGraphViewer().getPreviousItemAction();
861 fPreviousResourceAction.setText(Messages.ControlFlowView_previousProcessActionNameText);
862 fPreviousResourceAction.setToolTipText(Messages.ControlFlowView_previousProcessActionToolTipText);
863 fNextResourceAction = fTimeGraphCombo.getTimeGraphViewer().getNextItemAction();
864 fNextResourceAction.setText(Messages.ControlFlowView_nextProcessActionNameText);
865 fNextResourceAction.setToolTipText(Messages.ControlFlowView_nextProcessActionToolTipText);
866 }
867
868 private void contributeToActionBars() {
869 IActionBars bars = getViewSite().getActionBars();
870 fillLocalToolBar(bars.getToolBarManager());
871 }
872
873 private void fillLocalToolBar(IToolBarManager manager) {
874 manager.add(fTimeGraphCombo.getTimeGraphViewer().getShowLegendAction());
875 manager.add(new Separator());
876 manager.add(fTimeGraphCombo.getTimeGraphViewer().getResetScaleAction());
877 manager.add(fTimeGraphCombo.getTimeGraphViewer().getPreviousEventAction());
878 manager.add(fTimeGraphCombo.getTimeGraphViewer().getNextEventAction());
879 manager.add(fPreviousResourceAction);
880 manager.add(fNextResourceAction);
881 manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomInAction());
882 manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomOutAction());
883 manager.add(new Separator());
884 }
885 }
This page took 0.05062 seconds and 5 git commands to generate.