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