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