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