Bug 378402: Implementation of ControlFlow view and Resources view for
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.kernel.ui / src / org / eclipse / linuxtools / internal / lttng2 / kernel / ui / views / resources / ResourcesView.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.resources;
14
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Iterator;
18 import java.util.List;
19
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.core.runtime.NullProgressMonitor;
22 import org.eclipse.jface.action.Action;
23 import org.eclipse.jface.action.IToolBarManager;
24 import org.eclipse.jface.action.Separator;
25 import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Messages;
26 import org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.resources.ResourcesEntry.Type;
27 import org.eclipse.linuxtools.lttng2.kernel.core.trace.Attributes;
28 import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace;
29 import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTimestamp;
30 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
31 import org.eclipse.linuxtools.tmf.core.event.TmfEvent;
32 import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
33 import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
34 import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
35 import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
36 import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
37 import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
38 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal;
39 import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
40 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
41 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
42 import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemQuerier;
43 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
44 import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
45 import org.eclipse.linuxtools.tmf.ui.views.TmfView;
46 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
47 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
48 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
49 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
50 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphViewer;
51 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
52 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
53 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent;
54 import org.eclipse.swt.SWT;
55 import org.eclipse.swt.widgets.Composite;
56 import org.eclipse.swt.widgets.Display;
57 import org.eclipse.ui.IActionBars;
58
59 public class ResourcesView extends TmfView {
60
61 // ------------------------------------------------------------------------
62 // Constants
63 // ------------------------------------------------------------------------
64
65 /**
66 * View ID.
67 */
68 public static final String ID = "org.eclipse.linuxtools.lttng2.kernel.ui.views.resources"; //$NON-NLS-1$
69
70 /**
71 * Initial time range
72 */
73 private static final long INITIAL_WINDOW_OFFSET = (1L * 100 * 1000 * 1000); // .1sec
74
75 // ------------------------------------------------------------------------
76 // Fields
77 // ------------------------------------------------------------------------
78
79 // The time graph viewer
80 TimeGraphViewer fTimeGraphViewer;
81
82 // The selected experiment
83 private TmfExperiment<ITmfEvent> fSelectedExperiment;
84
85 // The time graph entry list
86 private ArrayList<TraceEntry> fEntryList;
87
88 // The start time
89 private long fStartTime;
90
91 // The end time
92 private long fEndTime;
93
94 // The display width
95 private int fDisplayWidth;
96
97 // The next resource action
98 private Action fNextResourceAction;
99
100 // The previous resource action
101 private Action fPreviousResourceAction;
102
103 // The zoom thread
104 private ZoomThread fZoomThread;
105
106 // ------------------------------------------------------------------------
107 // Classes
108 // ------------------------------------------------------------------------
109
110 private class TraceEntry implements ITimeGraphEntry {
111 private CtfKernelTrace fTrace;
112 public ArrayList<ResourcesEntry> fChildren;
113 public String fName;
114
115 public TraceEntry(CtfKernelTrace trace, String name) {
116 fTrace = trace;
117 fChildren = new ArrayList<ResourcesEntry>();
118 fName = name;
119 }
120
121 @Override
122 public ITimeGraphEntry getParent() {
123 return null;
124 }
125
126 @Override
127 public boolean hasChildren() {
128 return fChildren != null && fChildren.size() > 0;
129 }
130
131 @Override
132 public ResourcesEntry[] getChildren() {
133 return fChildren.toArray(new ResourcesEntry[0]);
134 }
135
136 @Override
137 public String getName() {
138 return fName;
139 }
140
141 @Override
142 public long getStartTime() {
143 return -1;
144 }
145
146 @Override
147 public long getEndTime() {
148 return -1;
149 }
150
151 @Override
152 public Iterator<ITimeEvent> getTimeEventsIterator() {
153 return null;
154 }
155
156 @Override
157 public <T extends ITimeEvent> Iterator<T> getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) {
158 return null;
159 }
160
161 public CtfKernelTrace getTrace() {
162 return fTrace;
163 }
164
165 public void addChild(ResourcesEntry entry) {
166 int index;
167 for (index = 0; index < fChildren.size(); index++) {
168 ResourcesEntry other = fChildren.get(index);
169 if (entry.getType().compareTo(other.getType()) < 0) {
170 break;
171 } else if (entry.getType().equals(other.getType())) {
172 if (entry.getId() < other.getId()) {
173 break;
174 }
175 }
176 }
177 entry.setParent(this);
178 fChildren.add(index, entry);
179 }
180 }
181
182 private class ZoomThread extends Thread {
183 private long fZoomStartTime;
184 private long fZoomEndTime;
185 private IProgressMonitor fMonitor;
186
187 public ZoomThread(long startTime, long endTime) {
188 super("ResourcesView zoom"); //$NON-NLS-1$
189 fZoomStartTime = startTime;
190 fZoomEndTime = endTime;
191 fMonitor = new NullProgressMonitor();
192 }
193
194 @Override
195 public void run() {
196 if (fEntryList == null) {
197 return;
198 }
199 long resolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
200 for (TraceEntry traceEntry : fEntryList) {
201 for (ITimeGraphEntry child : traceEntry.getChildren()) {
202 ResourcesEntry entry = (ResourcesEntry) child;
203 if (fMonitor.isCanceled()) {
204 break;
205 }
206 List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, resolution, true, fMonitor);
207 if (fMonitor.isCanceled()) {
208 break;
209 }
210 entry.setZoomedEventList(zoomedEventList);
211 redraw();
212 }
213 }
214 }
215
216 public void cancel() {
217 fMonitor.setCanceled(true);
218 }
219 }
220
221 // ------------------------------------------------------------------------
222 // Constructors
223 // ------------------------------------------------------------------------
224
225 public ResourcesView() {
226 super(ID);
227 fDisplayWidth = Display.getDefault().getBounds().width;
228 }
229
230 // ------------------------------------------------------------------------
231 // ViewPart
232 // ------------------------------------------------------------------------
233
234 /* (non-Javadoc)
235 * @see org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse.swt.widgets.Composite)
236 */
237 @Override
238 public void createPartControl(Composite parent) {
239 fTimeGraphViewer = new TimeGraphViewer(parent, SWT.NONE);
240
241 fTimeGraphViewer.setTimeGraphProvider(new ResourcesPresentationProvider());
242
243 fTimeGraphViewer.setTimeCalendarFormat(true);
244
245 fTimeGraphViewer.addRangeListener(new ITimeGraphRangeListener() {
246 @Override
247 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
248 long startTime = event.getStartTime();
249 long endTime = event.getEndTime();
250 TmfTimeRange range = new TmfTimeRange(new CtfTmfTimestamp(startTime), new CtfTmfTimestamp(endTime));
251 TmfTimestamp time = new CtfTmfTimestamp(fTimeGraphViewer.getSelectedTime());
252 broadcast(new TmfRangeSynchSignal(ResourcesView.this, range, time));
253 startZoomThread(startTime, endTime);
254 }
255 });
256
257 fTimeGraphViewer.addTimeListener(new ITimeGraphTimeListener() {
258 @Override
259 public void timeSelected(TimeGraphTimeEvent event) {
260 long time = event.getTime();
261 broadcast(new TmfTimeSynchSignal(ResourcesView.this, new CtfTmfTimestamp(time)));
262 }
263 });
264
265 final Thread thread = new Thread("ResourcesView build") { //$NON-NLS-1$
266 @Override
267 public void run() {
268 if (TmfExperiment.getCurrentExperiment() != null) {
269 selectExperiment(TmfExperiment.getCurrentExperiment());
270 }
271 }
272 };
273 thread.start();
274
275 // View Action Handling
276 makeActions();
277 contributeToActionBars();
278 }
279
280 /* (non-Javadoc)
281 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
282 */
283 @Override
284 public void setFocus() {
285 fTimeGraphViewer.setFocus();
286 }
287
288 // ------------------------------------------------------------------------
289 // Signal handlers
290 // ------------------------------------------------------------------------
291
292 @TmfSignalHandler
293 public void experimentSelected(final TmfExperimentSelectedSignal<? extends TmfEvent> signal) {
294 if (signal.getExperiment().equals(fSelectedExperiment)) {
295 return;
296 }
297
298 final Thread thread = new Thread("ResourcesView build") { //$NON-NLS-1$
299 @Override
300 public void run() {
301 selectExperiment(signal.getExperiment());
302 }
303 };
304 thread.start();
305 }
306
307 @TmfSignalHandler
308 public void synchToTime(final TmfTimeSynchSignal signal) {
309 if (signal.getSource() == this) {
310 return;
311 }
312 final long time = signal.getCurrentTime().normalize(0, -9).getValue();
313 Display.getDefault().asyncExec(new Runnable() {
314 @Override
315 public void run() {
316 if (fTimeGraphViewer.getControl().isDisposed()) {
317 return;
318 }
319 fTimeGraphViewer.setSelectedTime(time, true);
320 }
321 });
322 }
323
324 @TmfSignalHandler
325 public void synchToRange(final TmfRangeSynchSignal signal) {
326 if (signal.getSource() == this) {
327 return;
328 }
329 final long startTime = signal.getCurrentRange().getStartTime().normalize(0, -9).getValue();
330 final long endTime = signal.getCurrentRange().getEndTime().normalize(0, -9).getValue();
331 final long time = signal.getCurrentTime().normalize(0, -9).getValue();
332 Display.getDefault().asyncExec(new Runnable() {
333 @Override
334 public void run() {
335 if (fTimeGraphViewer.getControl().isDisposed()) {
336 return;
337 }
338 fTimeGraphViewer.setStartFinishTime(startTime, endTime);
339 fTimeGraphViewer.setSelectedTime(time, true);
340 startZoomThread(startTime, endTime);
341 }
342 });
343 }
344
345 // ------------------------------------------------------------------------
346 // Internal
347 // ------------------------------------------------------------------------
348
349 @SuppressWarnings("unchecked")
350 private void selectExperiment(TmfExperiment<?> experiment) {
351 fStartTime = Long.MAX_VALUE;
352 fEndTime = Long.MIN_VALUE;
353 fSelectedExperiment = (TmfExperiment<ITmfEvent>) experiment;
354 fEntryList = new ArrayList<TraceEntry>();
355 for (ITmfTrace<?> trace : experiment.getTraces()) {
356 if (trace instanceof CtfKernelTrace) {
357 CtfKernelTrace ctfKernelTrace = (CtfKernelTrace) trace;
358 TraceEntry groupEntry = new TraceEntry(ctfKernelTrace, trace.getName());
359 fEntryList.add(groupEntry);
360 IStateSystemQuerier ssq = ctfKernelTrace.getStateSystem();
361 long startTime = ssq.getStartTime();
362 long endTime = ssq.getCurrentEndTime() + 1;
363 fStartTime = Math.min(fStartTime, startTime);
364 fEndTime = Math.max(fEndTime, endTime);
365 List<Integer> cpuQuarks = ssq.getQuarks(Attributes.CPUS, "*"); //$NON-NLS-1$
366 ResourcesEntry[] cpuEntries = new ResourcesEntry[cpuQuarks.size()];
367 for (int i = 0; i < cpuQuarks.size(); i++) {
368 int cpuQuark = cpuQuarks.get(i);
369 int cpu = Integer.parseInt(ssq.getAttributeName(cpuQuark));
370 ResourcesEntry entry = new ResourcesEntry(cpuQuark, ctfKernelTrace, Type.CPU, cpu);
371 groupEntry.addChild(entry);
372 cpuEntries[i] = entry;
373 }
374 List<Integer> irqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.IRQS, "*"); //$NON-NLS-1$
375 ResourcesEntry[] irqEntries = new ResourcesEntry[irqQuarks.size()];
376 for (int i = 0; i < irqQuarks.size(); i++) {
377 int irqQuark = irqQuarks.get(i);
378 int irq = Integer.parseInt(ssq.getAttributeName(irqQuark));
379 ResourcesEntry entry = new ResourcesEntry(irqQuark, ctfKernelTrace, Type.IRQ, irq);
380 groupEntry.addChild(entry);
381 irqEntries[i] = entry;
382 }
383 List<Integer> softIrqQuarks = ssq.getQuarks(Attributes.RESOURCES, Attributes.SOFT_IRQS, "*"); //$NON-NLS-1$
384 ResourcesEntry[] softIrqEntries = new ResourcesEntry[softIrqQuarks.size()];
385 for (int i = 0; i < softIrqQuarks.size(); i++) {
386 int softIrqQuark = softIrqQuarks.get(i);
387 int softIrq = Integer.parseInt(ssq.getAttributeName(softIrqQuark));
388 ResourcesEntry entry = new ResourcesEntry(softIrqQuark, ctfKernelTrace, Type.SOFT_IRQ, softIrq);
389 groupEntry.addChild(entry);
390 softIrqEntries[i] = entry;
391 }
392 }
393 }
394 refresh(INITIAL_WINDOW_OFFSET);
395 for (TraceEntry traceEntry : fEntryList) {
396 CtfKernelTrace ctfKernelTrace = ((TraceEntry) traceEntry).getTrace();
397 IStateSystemQuerier ssq = ctfKernelTrace.getStateSystem();
398 long startTime = ssq.getStartTime();
399 long endTime = ssq.getCurrentEndTime() + 1;
400 long resolution = (endTime - startTime) / fDisplayWidth;
401 for (ResourcesEntry entry : traceEntry.getChildren()) {
402 List<ITimeEvent> eventList = getEventList(entry, startTime, endTime, resolution, false, new NullProgressMonitor());
403 entry.setEventList(eventList);
404 redraw();
405 }
406 }
407 }
408
409 private List<ITimeEvent> getEventList(ResourcesEntry entry, long startTime, long endTime, long resolution, boolean includeNull, IProgressMonitor monitor) {
410 if (endTime <= startTime) {
411 return null;
412 }
413 IStateSystemQuerier ssq = entry.getTrace().getStateSystem();
414 List<ITimeEvent> eventList = null;
415 int quark = entry.getQuark();
416 try {
417 if (entry.getType().equals(Type.CPU)) {
418 int statusQuark = ssq.getQuarkRelative(quark, Attributes.STATUS);
419 List<ITmfStateInterval> statusIntervals = ssq.queryHistoryRange(statusQuark, startTime, endTime - 1, resolution);
420 eventList = new ArrayList<ITimeEvent>(statusIntervals.size());
421 long lastEndTime = -1;
422 for (ITmfStateInterval statusInterval : statusIntervals) {
423 if (monitor.isCanceled()) {
424 return null;
425 }
426 int status = statusInterval.getStateValue().unboxInt();
427 long time = statusInterval.getStartTime();
428 long duration = statusInterval.getEndTime() - time + 1;
429 if (!statusInterval.getStateValue().isNull()) {
430 if (lastEndTime != time && lastEndTime != -1) {
431 eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
432 }
433 eventList.add(new ResourcesEvent(entry, time, duration, status));
434 lastEndTime = time + duration;
435 } else {
436 if (includeNull) {
437 eventList.add(new ResourcesEvent(entry, time, duration));
438 }
439 }
440 }
441 } else if (entry.getType().equals(Type.IRQ)) {
442 List<ITmfStateInterval> irqIntervals = ssq.queryHistoryRange(quark, startTime, endTime - 1, resolution);
443 eventList = new ArrayList<ITimeEvent>(irqIntervals.size());
444 long lastEndTime = -1;
445 boolean lastIsNull = true;
446 for (ITmfStateInterval irqInterval : irqIntervals) {
447 if (monitor.isCanceled()) {
448 return null;
449 }
450 long time = irqInterval.getStartTime();
451 long duration = irqInterval.getEndTime() - time + 1;
452 if (!irqInterval.getStateValue().isNull()) {
453 int cpu = irqInterval.getStateValue().unboxInt();
454 eventList.add(new ResourcesEvent(entry, time, duration, cpu));
455 lastIsNull = false;
456 } else {
457 if (lastEndTime != time && lastEndTime != -1 && lastIsNull) {
458 eventList.add(new ResourcesEvent(entry, lastEndTime, time - lastEndTime, -1));
459 }
460 if (includeNull) {
461 eventList.add(new ResourcesEvent(entry, time, duration));
462 }
463 lastIsNull = true;
464 }
465 lastEndTime = time + duration;
466 }
467 } else if (entry.getType().equals(Type.SOFT_IRQ)) {
468 List<ITmfStateInterval> softIrqIntervals = ssq.queryHistoryRange(quark, startTime, endTime - 1, resolution);
469 eventList = new ArrayList<ITimeEvent>(softIrqIntervals.size());
470 long lastEndTime = -1;
471 boolean lastIsNull = true;
472 for (ITmfStateInterval softIrqInterval : softIrqIntervals) {
473 if (monitor.isCanceled()) {
474 return null;
475 }
476 long time = softIrqInterval.getStartTime();
477 long duration = softIrqInterval.getEndTime() - time + 1;
478 if (!softIrqInterval.getStateValue().isNull()) {
479 int cpu = softIrqInterval.getStateValue().unboxInt();
480 eventList.add(new ResourcesEvent(entry, time, duration, cpu));
481 } else {
482 if (lastEndTime != time && lastEndTime != -1 && lastIsNull) {
483 eventList.add(new ResourcesEvent(entry, lastEndTime, time - lastEndTime, -1));
484 }
485 if (includeNull) {
486 eventList.add(new ResourcesEvent(entry, time, duration));
487 }
488 lastIsNull = true;
489 }
490 lastEndTime = time + duration;
491 }
492 }
493 } catch (AttributeNotFoundException e) {
494 e.printStackTrace();
495 } catch (TimeRangeException e) {
496 e.printStackTrace();
497 } catch (StateValueTypeException e) {
498 e.printStackTrace();
499 }
500 return eventList;
501 }
502
503 private void refresh(final long windowRange) {
504 Display.getDefault().asyncExec(new Runnable() {
505 @Override
506 public void run() {
507 if (fTimeGraphViewer.getControl().isDisposed()) {
508 return;
509 }
510 ITimeGraphEntry[] entries = fEntryList.toArray(new ITimeGraphEntry[0]);
511 Arrays.sort(entries);
512 fTimeGraphViewer.setInput(entries);
513 fTimeGraphViewer.setTimeBounds(fStartTime, fEndTime);
514
515 long endTime = fStartTime + windowRange;
516
517 if (fEndTime < endTime) {
518 endTime = fEndTime;
519 }
520 fTimeGraphViewer.setStartFinishTime(fStartTime, endTime);
521
522 startZoomThread(fStartTime, endTime);
523 }
524 });
525 }
526
527
528 private void redraw() {
529 Display.getDefault().asyncExec(new Runnable() {
530 @Override
531 public void run() {
532 if (fTimeGraphViewer.getControl().isDisposed()) {
533 return;
534 }
535 fTimeGraphViewer.getControl().redraw();
536 fTimeGraphViewer.getControl().update();
537 }
538 });
539 }
540
541 private void startZoomThread(long startTime, long endTime) {
542 if (fZoomThread != null) {
543 fZoomThread.cancel();
544 }
545 fZoomThread = new ZoomThread(startTime, endTime);
546 fZoomThread.start();
547 }
548
549 private void makeActions() {
550 fPreviousResourceAction = fTimeGraphViewer.getPreviousItemAction();
551 fPreviousResourceAction.setText(Messages.ResourcesView_previousResourceActionNameText);
552 fPreviousResourceAction.setToolTipText(Messages.ResourcesView_previousResourceActionToolTipText);
553 fNextResourceAction = fTimeGraphViewer.getNextItemAction();
554 fNextResourceAction.setText(Messages.ResourcesView_nextResourceActionNameText);
555 fNextResourceAction.setToolTipText(Messages.ResourcesView_previousResourceActionToolTipText);
556 }
557
558 private void contributeToActionBars() {
559 IActionBars bars = getViewSite().getActionBars();
560 fillLocalToolBar(bars.getToolBarManager());
561 }
562
563 private void fillLocalToolBar(IToolBarManager manager) {
564 manager.add(fTimeGraphViewer.getShowLegendAction());
565 manager.add(new Separator());
566 manager.add(fTimeGraphViewer.getResetScaleAction());
567 manager.add(fTimeGraphViewer.getPreviousEventAction());
568 manager.add(fTimeGraphViewer.getNextEventAction());
569 manager.add(fPreviousResourceAction);
570 manager.add(fNextResourceAction);
571 manager.add(fTimeGraphViewer.getZoomInAction());
572 manager.add(fTimeGraphViewer.getZoomOutAction());
573 manager.add(new Separator());
574 }
575 }
This page took 0.050256 seconds and 6 git commands to generate.