1 /*******************************************************************************
2 * Copyright (c) 2012 Ericsson
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
10 * Patrick Tasse - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.ui
.views
.resources
;
15 import java
.util
.ArrayList
;
16 import java
.util
.Arrays
;
17 import java
.util
.Iterator
;
18 import java
.util
.List
;
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
;
59 public class ResourcesView
extends TmfView
{
61 // ------------------------------------------------------------------------
63 // ------------------------------------------------------------------------
68 public static final String ID
= "org.eclipse.linuxtools.lttng2.kernel.ui.views.resources"; //$NON-NLS-1$
73 private static final long INITIAL_WINDOW_OFFSET
= (1L * 100 * 1000 * 1000); // .1sec
75 // ------------------------------------------------------------------------
77 // ------------------------------------------------------------------------
79 // The time graph viewer
80 TimeGraphViewer fTimeGraphViewer
;
82 // The selected experiment
83 private TmfExperiment
<ITmfEvent
> fSelectedExperiment
;
85 // The time graph entry list
86 private ArrayList
<TraceEntry
> fEntryList
;
89 private long fStartTime
;
92 private long fEndTime
;
95 private int fDisplayWidth
;
97 // The next resource action
98 private Action fNextResourceAction
;
100 // The previous resource action
101 private Action fPreviousResourceAction
;
104 private ZoomThread fZoomThread
;
106 // ------------------------------------------------------------------------
108 // ------------------------------------------------------------------------
110 private class TraceEntry
implements ITimeGraphEntry
{
111 private CtfKernelTrace fTrace
;
112 public ArrayList
<ResourcesEntry
> fChildren
;
115 public TraceEntry(CtfKernelTrace trace
, String name
) {
117 fChildren
= new ArrayList
<ResourcesEntry
>();
122 public ITimeGraphEntry
getParent() {
127 public boolean hasChildren() {
128 return fChildren
!= null && fChildren
.size() > 0;
132 public ResourcesEntry
[] getChildren() {
133 return fChildren
.toArray(new ResourcesEntry
[0]);
137 public String
getName() {
142 public long getStartTime() {
147 public long getEndTime() {
152 public Iterator
<ITimeEvent
> getTimeEventsIterator() {
157 public <T
extends ITimeEvent
> Iterator
<T
> getTimeEventsIterator(long startTime
, long stopTime
, long visibleDuration
) {
161 public CtfKernelTrace
getTrace() {
165 public void addChild(ResourcesEntry entry
) {
167 for (index
= 0; index
< fChildren
.size(); index
++) {
168 ResourcesEntry other
= fChildren
.get(index
);
169 if (entry
.getType().compareTo(other
.getType()) < 0) {
171 } else if (entry
.getType().equals(other
.getType())) {
172 if (entry
.getId() < other
.getId()) {
177 entry
.setParent(this);
178 fChildren
.add(index
, entry
);
182 private class ZoomThread
extends Thread
{
183 private long fZoomStartTime
;
184 private long fZoomEndTime
;
185 private IProgressMonitor fMonitor
;
187 public ZoomThread(long startTime
, long endTime
) {
188 super("ResourcesView zoom"); //$NON-NLS-1$
189 fZoomStartTime
= startTime
;
190 fZoomEndTime
= endTime
;
191 fMonitor
= new NullProgressMonitor();
196 if (fEntryList
== null) {
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()) {
206 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, fZoomStartTime
, fZoomEndTime
, resolution
, true, fMonitor
);
207 if (fMonitor
.isCanceled()) {
210 entry
.setZoomedEventList(zoomedEventList
);
216 public void cancel() {
217 fMonitor
.setCanceled(true);
221 // ------------------------------------------------------------------------
223 // ------------------------------------------------------------------------
225 public ResourcesView() {
227 fDisplayWidth
= Display
.getDefault().getBounds().width
;
230 // ------------------------------------------------------------------------
232 // ------------------------------------------------------------------------
235 * @see org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse.swt.widgets.Composite)
238 public void createPartControl(Composite parent
) {
239 fTimeGraphViewer
= new TimeGraphViewer(parent
, SWT
.NONE
);
241 fTimeGraphViewer
.setTimeGraphProvider(new ResourcesPresentationProvider());
243 fTimeGraphViewer
.setTimeCalendarFormat(true);
245 fTimeGraphViewer
.addRangeListener(new ITimeGraphRangeListener() {
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
);
257 fTimeGraphViewer
.addTimeListener(new ITimeGraphTimeListener() {
259 public void timeSelected(TimeGraphTimeEvent event
) {
260 long time
= event
.getTime();
261 broadcast(new TmfTimeSynchSignal(ResourcesView
.this, new CtfTmfTimestamp(time
)));
265 final Thread thread
= new Thread("ResourcesView build") { //$NON-NLS-1$
268 if (TmfExperiment
.getCurrentExperiment() != null) {
269 selectExperiment(TmfExperiment
.getCurrentExperiment());
275 // View Action Handling
277 contributeToActionBars();
281 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
284 public void setFocus() {
285 fTimeGraphViewer
.setFocus();
288 // ------------------------------------------------------------------------
290 // ------------------------------------------------------------------------
293 public void experimentSelected(final TmfExperimentSelectedSignal
<?
extends TmfEvent
> signal
) {
294 if (signal
.getExperiment().equals(fSelectedExperiment
)) {
298 final Thread thread
= new Thread("ResourcesView build") { //$NON-NLS-1$
301 selectExperiment(signal
.getExperiment());
308 public void synchToTime(final TmfTimeSynchSignal signal
) {
309 if (signal
.getSource() == this) {
312 final long time
= signal
.getCurrentTime().normalize(0, -9).getValue();
313 Display
.getDefault().asyncExec(new Runnable() {
316 if (fTimeGraphViewer
.getControl().isDisposed()) {
319 fTimeGraphViewer
.setSelectedTime(time
, true);
325 public void synchToRange(final TmfRangeSynchSignal signal
) {
326 if (signal
.getSource() == this) {
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() {
335 if (fTimeGraphViewer
.getControl().isDisposed()) {
338 fTimeGraphViewer
.setStartFinishTime(startTime
, endTime
);
339 fTimeGraphViewer
.setSelectedTime(time
, true);
340 startZoomThread(startTime
, endTime
);
345 // ------------------------------------------------------------------------
347 // ------------------------------------------------------------------------
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
;
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
;
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
;
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
);
409 private List
<ITimeEvent
> getEventList(ResourcesEntry entry
, long startTime
, long endTime
, long resolution
, boolean includeNull
, IProgressMonitor monitor
) {
410 if (endTime
<= startTime
) {
413 IStateSystemQuerier ssq
= entry
.getTrace().getStateSystem();
414 List
<ITimeEvent
> eventList
= null;
415 int quark
= entry
.getQuark();
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()) {
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
));
433 eventList
.add(new ResourcesEvent(entry
, time
, duration
, status
));
434 lastEndTime
= time
+ duration
;
437 eventList
.add(new ResourcesEvent(entry
, time
, duration
));
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()) {
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
));
457 if (lastEndTime
!= time
&& lastEndTime
!= -1 && lastIsNull
) {
458 eventList
.add(new ResourcesEvent(entry
, lastEndTime
, time
- lastEndTime
, -1));
461 eventList
.add(new ResourcesEvent(entry
, time
, duration
));
465 lastEndTime
= time
+ duration
;
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()) {
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
));
482 if (lastEndTime
!= time
&& lastEndTime
!= -1 && lastIsNull
) {
483 eventList
.add(new ResourcesEvent(entry
, lastEndTime
, time
- lastEndTime
, -1));
486 eventList
.add(new ResourcesEvent(entry
, time
, duration
));
490 lastEndTime
= time
+ duration
;
493 } catch (AttributeNotFoundException e
) {
495 } catch (TimeRangeException e
) {
497 } catch (StateValueTypeException e
) {
503 private void refresh(final long windowRange
) {
504 Display
.getDefault().asyncExec(new Runnable() {
507 if (fTimeGraphViewer
.getControl().isDisposed()) {
510 ITimeGraphEntry
[] entries
= fEntryList
.toArray(new ITimeGraphEntry
[0]);
511 Arrays
.sort(entries
);
512 fTimeGraphViewer
.setInput(entries
);
513 fTimeGraphViewer
.setTimeBounds(fStartTime
, fEndTime
);
515 long endTime
= fStartTime
+ windowRange
;
517 if (fEndTime
< endTime
) {
520 fTimeGraphViewer
.setStartFinishTime(fStartTime
, endTime
);
522 startZoomThread(fStartTime
, endTime
);
528 private void redraw() {
529 Display
.getDefault().asyncExec(new Runnable() {
532 if (fTimeGraphViewer
.getControl().isDisposed()) {
535 fTimeGraphViewer
.getControl().redraw();
536 fTimeGraphViewer
.getControl().update();
541 private void startZoomThread(long startTime
, long endTime
) {
542 if (fZoomThread
!= null) {
543 fZoomThread
.cancel();
545 fZoomThread
= new ZoomThread(startTime
, endTime
);
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
);
558 private void contributeToActionBars() {
559 IActionBars bars
= getViewSite().getActionBars();
560 fillLocalToolBar(bars
.getToolBarManager());
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());