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