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