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