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
.HashMap
;
18 import java
.util
.Iterator
;
19 import java
.util
.List
;
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
.StateItem
;
49 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphPresentationProvider
;
50 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphRangeUpdateEvent
;
51 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphTimeEvent
;
52 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.TimeGraphViewer
;
53 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
54 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
55 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.TimeEvent
;
56 import org
.eclipse
.swt
.SWT
;
57 import org
.eclipse
.swt
.graphics
.RGB
;
58 import org
.eclipse
.swt
.widgets
.Composite
;
59 import org
.eclipse
.swt
.widgets
.Display
;
60 import org
.eclipse
.ui
.IActionBars
;
62 public class ResourcesView
extends TmfView
{
64 // ------------------------------------------------------------------------
66 // ------------------------------------------------------------------------
71 public static final String ID
= "org.eclipse.linuxtools.lttng2.kernel.ui.views.resources"; //$NON-NLS-1$
73 // ------------------------------------------------------------------------
75 // ------------------------------------------------------------------------
77 // The time graph viewer
78 TimeGraphViewer fTimeGraphViewer
;
80 // The selected experiment
81 private TmfExperiment
<ITmfEvent
> fSelectedExperiment
;
83 // The time graph entry list
84 private ArrayList
<TraceEntry
> fEntryList
;
87 private long fStartTime
;
90 private long fEndTime
;
93 private int fDisplayWidth
;
95 // The next resource action
96 private Action fNextResourceAction
;
98 // The previous resource action
99 private Action fPreviousResourceAction
;
103 private ZoomThread fZoomThread
;
105 // ------------------------------------------------------------------------
107 // ------------------------------------------------------------------------
109 private class TraceEntry
implements ITimeGraphEntry
{
110 private CtfKernelTrace fTrace
;
111 public ArrayList
<ResourcesEntry
> fChildren
;
114 public TraceEntry(CtfKernelTrace trace
, String name
) {
116 fChildren
= new ArrayList
<ResourcesEntry
>();
121 public ITimeGraphEntry
getParent() {
126 public boolean hasChildren() {
127 return fChildren
!= null && fChildren
.size() > 0;
131 public ResourcesEntry
[] getChildren() {
132 return fChildren
.toArray(new ResourcesEntry
[0]);
136 public String
getName() {
141 public long getStartTime() {
146 public long getEndTime() {
151 public Iterator
<ITimeEvent
> getTimeEventsIterator() {
156 public <T
extends ITimeEvent
> Iterator
<T
> getTimeEventsIterator(long startTime
, long stopTime
, long visibleDuration
) {
160 public CtfKernelTrace
getTrace() {
164 public void addChild(ResourcesEntry entry
) {
166 for (index
= 0; index
< fChildren
.size(); index
++) {
167 ResourcesEntry other
= fChildren
.get(index
);
168 if (entry
.getType().compareTo(other
.getType()) < 0) {
170 } else if (entry
.getType().equals(other
.getType())) {
171 if (entry
.getId() < other
.getId()) {
176 entry
.setParent(this);
177 fChildren
.add(index
, entry
);
181 private class ZoomThread
extends Thread
{
182 private long fStartTime
;
183 private long fEndTime
;
184 private boolean fCancelled
= false;
186 public ZoomThread(long startTime
, long endTime
) {
187 super("ResourcesView zoom"); //$NON-NLS-1$
188 fStartTime
= startTime
;
194 if (fEntryList
== null) {
197 long resolution
= Math
.max(1, (fEndTime
- fStartTime
) / fDisplayWidth
);
198 for (TraceEntry traceEntry
: fEntryList
) {
199 for (ITimeGraphEntry child
: traceEntry
.getChildren()) {
200 ResourcesEntry entry
= (ResourcesEntry
) child
;
204 List
<ITimeEvent
> zoomedEventList
= getEventList(entry
, fStartTime
, fEndTime
, resolution
, true);
205 entry
.setZoomedEventList(zoomedEventList
);
211 public void cancel() {
216 // ------------------------------------------------------------------------
218 // ------------------------------------------------------------------------
220 public ResourcesView() {
222 fDisplayWidth
= Display
.getDefault().getBounds().width
;
225 // ------------------------------------------------------------------------
227 // ------------------------------------------------------------------------
230 * @see org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse.swt.widgets.Composite)
233 public void createPartControl(Composite parent
) {
234 fTimeGraphViewer
= new TimeGraphViewer(parent
, SWT
.NONE
);
236 fTimeGraphViewer
.setTimeGraphProvider(new TimeGraphPresentationProvider() {
237 private static final String UNKNOWN
= "UNKNOWN"; //$NON-NLS-1$
238 private static final String IDLE
= "IDLE"; //$NON-NLS-1$
239 private static final String BUSY
= "BUSY"; //$NON-NLS-1$
240 private static final String INTERRUPTED
= "INTERRUPTED"; //$NON-NLS-1$
241 private static final String RAISED
= "RAISED"; //$NON-NLS-1$
242 private static final String ACTIVE
= "ACTIVE"; //$NON-NLS-1$
245 public String
getStateTypeName() {
246 return Messages
.ResourcesView_stateTypeName
;
250 public String
getEventName(ITimeEvent event
) {
251 if (event
instanceof ResourcesEvent
) {
252 ResourcesEvent resourcesEvent
= (ResourcesEvent
) event
;
253 if (resourcesEvent
.getType() == Type
.CPU
) {
254 int currentThread
= resourcesEvent
.getValue();
255 if (currentThread
== 0) {
260 } else if (resourcesEvent
.getType() == Type
.IRQ
|| resourcesEvent
.getType() == Type
.SOFT_IRQ
) {
261 int cpu
= resourcesEvent
.getValue();
262 if (cpu
== Attributes
.SOFT_IRQ_RAISED
) {
274 public Map
<String
, String
> getEventHoverToolTipInfo(ITimeEvent event
) {
275 return new HashMap
<String
, String
>();
279 public StateItem
[] getStateTable() {
280 return new StateItem
[] {
281 new StateItem(new RGB(100, 100, 100), UNKNOWN
),
282 new StateItem(new RGB(200, 200, 200), IDLE
),
283 new StateItem(new RGB(0, 200, 0), BUSY
),
284 new StateItem(new RGB(200, 100, 100), INTERRUPTED
),
285 new StateItem(new RGB(200, 200, 0), RAISED
),
286 new StateItem(new RGB(200, 100, 100), ACTIVE
)
291 public int getEventTableIndex(ITimeEvent event
) {
292 if (event
instanceof ResourcesEvent
) {
293 ResourcesEvent resourcesEvent
= (ResourcesEvent
) event
;
294 if (resourcesEvent
.getType() == Type
.CPU
) {
295 int currentThread
= resourcesEvent
.getValue();
296 if (currentThread
== 0) {
301 } else if (resourcesEvent
.getType() == Type
.IRQ
|| resourcesEvent
.getType() == Type
.SOFT_IRQ
) {
302 int cpu
= resourcesEvent
.getValue();
303 if (cpu
== Attributes
.SOFT_IRQ_RAISED
) {
315 fTimeGraphViewer
.setTimeCalendarFormat(true);
317 fTimeGraphViewer
.addRangeListener(new ITimeGraphRangeListener() {
319 public void timeRangeUpdated(TimeGraphRangeUpdateEvent event
) {
320 long startTime
= event
.getStartTime();
321 long endTime
= event
.getEndTime();
322 TmfTimeRange range
= new TmfTimeRange(new CtfTmfTimestamp(startTime
), new CtfTmfTimestamp(endTime
));
323 TmfTimestamp time
= new CtfTmfTimestamp(fTimeGraphViewer
.getSelectedTime());
324 broadcast(new TmfRangeSynchSignal(ResourcesView
.this, range
, time
));
325 if (fZoomThread
!= null) {
326 fZoomThread
.cancel();
328 fZoomThread
= new ZoomThread(startTime
, endTime
);
333 fTimeGraphViewer
.addTimeListener(new ITimeGraphTimeListener() {
335 public void timeSelected(TimeGraphTimeEvent event
) {
336 long time
= event
.getTime();
337 broadcast(new TmfTimeSynchSignal(ResourcesView
.this, new CtfTmfTimestamp(time
)));
341 final Thread thread
= new Thread("ResourcesView build") { //$NON-NLS-1$
344 if (TmfExperiment
.getCurrentExperiment() != null) {
345 selectExperiment(TmfExperiment
.getCurrentExperiment());
351 // View Action Handling
353 contributeToActionBars();
357 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
360 public void setFocus() {
361 fTimeGraphViewer
.setFocus();
364 // ------------------------------------------------------------------------
366 // ------------------------------------------------------------------------
369 public void experimentSelected(final TmfExperimentSelectedSignal
<?
extends TmfEvent
> signal
) {
370 if (signal
.getExperiment().equals(fSelectedExperiment
)) {
374 final Thread thread
= new Thread("ResourcesView build") { //$NON-NLS-1$
377 selectExperiment(signal
.getExperiment());
383 public void synchToTime(final TmfTimeSynchSignal signal
) {
384 if (signal
.getSource() == this) {
387 final long time
= signal
.getCurrentTime().normalize(0, -9).getValue();
388 Display
.getDefault().asyncExec(new Runnable() {
391 if (fTimeGraphViewer
.getControl().isDisposed()) {
394 fTimeGraphViewer
.setSelectedTime(time
, true, signal
.getSource());
400 public void synchToRange(final TmfRangeSynchSignal signal
) {
401 if (signal
.getSource() == this) {
404 final long startTime
= signal
.getCurrentRange().getStartTime().normalize(0, -9).getValue();
405 final long endTime
= signal
.getCurrentRange().getEndTime().normalize(0, -9).getValue();
406 final long time
= signal
.getCurrentTime().normalize(0, -9).getValue();
407 Display
.getDefault().asyncExec(new Runnable() {
410 if (fTimeGraphViewer
.getControl().isDisposed()) {
413 fTimeGraphViewer
.setStartFinishTime(startTime
, endTime
);
414 fTimeGraphViewer
.setSelectedTime(time
, false, signal
.getSource());
419 // ------------------------------------------------------------------------
421 // ------------------------------------------------------------------------
423 @SuppressWarnings("unchecked")
424 private void selectExperiment(TmfExperiment
<?
> experiment
) {
425 fStartTime
= Long
.MAX_VALUE
;
426 fEndTime
= Long
.MIN_VALUE
;
427 fSelectedExperiment
= (TmfExperiment
<ITmfEvent
>) experiment
;
428 fEntryList
= new ArrayList
<TraceEntry
>();
429 for (ITmfTrace
<?
> trace
: experiment
.getTraces()) {
430 if (trace
instanceof CtfKernelTrace
) {
431 CtfKernelTrace ctfKernelTrace
= (CtfKernelTrace
) trace
;
432 TraceEntry groupEntry
= new TraceEntry(ctfKernelTrace
, trace
.getName());
433 fEntryList
.add(groupEntry
);
434 IStateSystemQuerier ssq
= ctfKernelTrace
.getStateSystem();
435 long startTime
= ssq
.getStartTime();
436 long endTime
= ssq
.getCurrentEndTime() + 1;
437 fStartTime
= Math
.min(fStartTime
, startTime
);
438 fEndTime
= Math
.max(fEndTime
, endTime
);
439 List
<Integer
> cpuQuarks
= ssq
.getQuarks(Attributes
.CPUS
, "*"); //$NON-NLS-1$
440 ResourcesEntry
[] cpuEntries
= new ResourcesEntry
[cpuQuarks
.size()];
441 for (int i
= 0; i
< cpuQuarks
.size(); i
++) {
442 int cpuQuark
= cpuQuarks
.get(i
);
443 int cpu
= Integer
.parseInt(ssq
.getAttributeName(cpuQuark
));
444 ResourcesEntry entry
= new ResourcesEntry(cpuQuark
, ctfKernelTrace
, Type
.CPU
, cpu
);
445 groupEntry
.addChild(entry
);
446 cpuEntries
[i
] = entry
;
448 List
<Integer
> irqQuarks
= ssq
.getQuarks(Attributes
.RESOURCES
, Attributes
.IRQS
, "*"); //$NON-NLS-1$
449 ResourcesEntry
[] irqEntries
= new ResourcesEntry
[irqQuarks
.size()];
450 for (int i
= 0; i
< irqQuarks
.size(); i
++) {
451 int irqQuark
= irqQuarks
.get(i
);
452 int irq
= Integer
.parseInt(ssq
.getAttributeName(irqQuark
));
453 ResourcesEntry entry
= new ResourcesEntry(irqQuark
, ctfKernelTrace
, Type
.IRQ
, irq
);
454 groupEntry
.addChild(entry
);
455 irqEntries
[i
] = entry
;
457 List
<Integer
> softIrqQuarks
= ssq
.getQuarks(Attributes
.RESOURCES
, Attributes
.SOFT_IRQS
, "*"); //$NON-NLS-1$
458 ResourcesEntry
[] softIrqEntries
= new ResourcesEntry
[softIrqQuarks
.size()];
459 for (int i
= 0; i
< softIrqQuarks
.size(); i
++) {
460 int softIrqQuark
= softIrqQuarks
.get(i
);
461 int softIrq
= Integer
.parseInt(ssq
.getAttributeName(softIrqQuark
));
462 ResourcesEntry entry
= new ResourcesEntry(softIrqQuark
, ctfKernelTrace
, Type
.SOFT_IRQ
, softIrq
);
463 groupEntry
.addChild(entry
);
464 softIrqEntries
[i
] = entry
;
469 for (TraceEntry traceEntry
: fEntryList
) {
470 CtfKernelTrace ctfKernelTrace
= ((TraceEntry
) traceEntry
).getTrace();
471 IStateSystemQuerier ssq
= ctfKernelTrace
.getStateSystem();
472 long startTime
= ssq
.getStartTime();
473 long endTime
= ssq
.getCurrentEndTime() + 1;
474 long resolution
= (endTime
- startTime
) / fDisplayWidth
;
475 for (ResourcesEntry entry
: traceEntry
.getChildren()) {
476 List
<ITimeEvent
> eventList
= getEventList(entry
, startTime
, endTime
, resolution
, false);
477 entry
.setEventList(eventList
);
483 private List
<ITimeEvent
> getEventList(ResourcesEntry entry
, long startTime
, long endTime
, long resolution
, boolean includeNull
) {
484 IStateSystemQuerier ssq
= entry
.getTrace().getStateSystem();
485 List
<ITimeEvent
> eventList
= null;
486 int quark
= entry
.getQuark();
488 if (entry
.getType().equals(Type
.CPU
)) {
489 int currentThreadQuark
= ssq
.getQuarkRelative(quark
, Attributes
.CURRENT_THREAD
);
490 List
<ITmfStateInterval
> currentThreadIntervals
= ssq
.queryHistoryRange(currentThreadQuark
, startTime
, endTime
- 1, resolution
);
491 eventList
= new ArrayList
<ITimeEvent
>(currentThreadIntervals
.size());
492 long lastEndTime
= -1;
493 for (ITmfStateInterval currentThreadInterval
: currentThreadIntervals
) {
494 if (!currentThreadInterval
.getStateValue().isNull()) {
495 int currentThread
= currentThreadInterval
.getStateValue().unboxInt();
496 long time
= currentThreadInterval
.getStartTime();
497 long duration
= currentThreadInterval
.getEndTime() - time
+ 1;
498 if (lastEndTime
!= time
&& lastEndTime
!= -1) {
499 eventList
.add(new TimeEvent(entry
, lastEndTime
, time
- lastEndTime
));
501 eventList
.add(new ResourcesEvent(entry
, time
, duration
, currentThread
));
502 lastEndTime
= time
+ duration
;
505 } else if (entry
.getType().equals(Type
.IRQ
)) {
506 List
<ITmfStateInterval
> irqIntervals
= ssq
.queryHistoryRange(quark
, startTime
, endTime
- 1, resolution
);
507 eventList
= new ArrayList
<ITimeEvent
>(irqIntervals
.size());
508 long lastEndTime
= -1;
509 boolean lastIsNull
= true;
510 for (ITmfStateInterval irqInterval
: irqIntervals
) {
511 long time
= irqInterval
.getStartTime();
512 long duration
= irqInterval
.getEndTime() - time
+ 1;
513 if (!irqInterval
.getStateValue().isNull()) {
514 int cpu
= irqInterval
.getStateValue().unboxInt();
515 eventList
.add(new ResourcesEvent(entry
, time
, duration
, cpu
));
518 if (lastEndTime
!= time
&& lastEndTime
!= -1 && lastIsNull
) {
519 eventList
.add(new ResourcesEvent(entry
, lastEndTime
, time
- lastEndTime
, -1));
522 eventList
.add(new ResourcesEvent(entry
, time
, duration
));
526 lastEndTime
= time
+ duration
;
528 } else if (entry
.getType().equals(Type
.SOFT_IRQ
)) {
529 List
<ITmfStateInterval
> softIrqIntervals
= ssq
.queryHistoryRange(quark
, startTime
, endTime
- 1, resolution
);
530 eventList
= new ArrayList
<ITimeEvent
>(softIrqIntervals
.size());
531 long lastEndTime
= -1;
532 boolean lastIsNull
= true;
533 for (ITmfStateInterval softIrqInterval
: softIrqIntervals
) {
534 long time
= softIrqInterval
.getStartTime();
535 long duration
= softIrqInterval
.getEndTime() - time
+ 1;
536 if (!softIrqInterval
.getStateValue().isNull()) {
537 int cpu
= softIrqInterval
.getStateValue().unboxInt();
538 eventList
.add(new ResourcesEvent(entry
, time
, duration
, cpu
));
540 if (lastEndTime
!= time
&& lastEndTime
!= -1 && lastIsNull
) {
541 eventList
.add(new ResourcesEvent(entry
, lastEndTime
, time
- lastEndTime
, -1));
544 eventList
.add(new ResourcesEvent(entry
, time
, duration
));
548 lastEndTime
= time
+ duration
;
551 } catch (AttributeNotFoundException e
) {
553 } catch (TimeRangeException e
) {
555 } catch (StateValueTypeException e
) {
561 private void refresh() {
562 Display
.getDefault().asyncExec(new Runnable() {
565 if (fTimeGraphViewer
.getControl().isDisposed()) {
568 ITimeGraphEntry
[] entries
= fEntryList
.toArray(new ITimeGraphEntry
[0]);
569 Arrays
.sort(entries
);
570 fTimeGraphViewer
.setInput(entries
);
571 fTimeGraphViewer
.setTimeBounds(fStartTime
, fEndTime
);
572 fTimeGraphViewer
.setStartFinishTime(fStartTime
, fEndTime
);
578 private void redraw() {
579 Display
.getDefault().asyncExec(new Runnable() {
582 if (fTimeGraphViewer
.getControl().isDisposed()) {
585 fTimeGraphViewer
.getControl().redraw();
586 fTimeGraphViewer
.getControl().update();
591 private void makeActions() {
592 fPreviousResourceAction
= fTimeGraphViewer
.getPreviousItemAction();
593 fPreviousResourceAction
.setText(Messages
.ResourcesView_previousResourceActionNameText
);
594 fPreviousResourceAction
.setToolTipText(Messages
.ResourcesView_previousResourceActionToolTipText
);
595 fNextResourceAction
= fTimeGraphViewer
.getNextItemAction();
596 fNextResourceAction
.setText(Messages
.ResourcesView_nextResourceActionNameText
);
597 fNextResourceAction
.setToolTipText(Messages
.ResourcesView_previousResourceActionToolTipText
);
600 private void contributeToActionBars() {
601 IActionBars bars
= getViewSite().getActionBars();
602 fillLocalToolBar(bars
.getToolBarManager());
605 private void fillLocalToolBar(IToolBarManager manager
) {
606 manager
.add(fTimeGraphViewer
.getShowLegendAction());
607 manager
.add(new Separator());
608 manager
.add(fTimeGraphViewer
.getResetScaleAction());
609 manager
.add(fTimeGraphViewer
.getPreviousEventAction());
610 manager
.add(fTimeGraphViewer
.getNextEventAction());
611 manager
.add(fPreviousResourceAction
);
612 manager
.add(fNextResourceAction
);
613 manager
.add(fTimeGraphViewer
.getZoomInAction());
614 manager
.add(fTimeGraphViewer
.getZoomOutAction());
615 manager
.add(new Separator());