1 /*******************************************************************************
2 * Copyright (c) 2015 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
.tracecompass
.tmf
.ui
.views
.timegraph
;
15 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
17 import java
.util
.ArrayList
;
18 import java
.util
.HashMap
;
19 import java
.util
.List
;
21 import java
.util
.concurrent
.CopyOnWriteArrayList
;
23 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
24 import org
.eclipse
.jdt
.annotation
.NonNull
;
25 import org
.eclipse
.jdt
.annotation
.Nullable
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceClosedSignal
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
32 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.TimeGraphPresentationProvider
;
33 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ILinkEvent
;
34 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.IMarkerEvent
;
35 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeEvent
;
36 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
37 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.model
.TimeGraphEntry
;
39 import com
.google
.common
.collect
.HashMultimap
;
40 import com
.google
.common
.collect
.Multimap
;
43 * An abstract time graph view where each entry's time event list is populated
44 * from a state system. The state system full state is queried in chronological
45 * order before creating the time event lists as this is optimal for state
50 public abstract class AbstractStateSystemTimeGraphView
extends AbstractTimeGraphView
{
52 // ------------------------------------------------------------------------
54 // ------------------------------------------------------------------------
56 private static final long MAX_INTERVALS
= 1000000;
58 // ------------------------------------------------------------------------
60 // ------------------------------------------------------------------------
62 /** The state system to entry list hash map */
63 private final Map
<ITmfStateSystem
, List
<TimeGraphEntry
>> fSSEntryListMap
= new HashMap
<>();
65 /** The trace to state system multi map */
66 private final Multimap
<ITmfTrace
, ITmfStateSystem
> fTraceSSMap
= HashMultimap
.create();
68 // ------------------------------------------------------------------------
70 // ------------------------------------------------------------------------
73 * Handler for state system queries
75 public interface IQueryHandler
{
77 * Handle a full or partial list of full states. This can be called many
78 * times for the same query if the query result is split, in which case
79 * the previous full state is null only the first time it is called, and
80 * set to the last full state of the previous call from then on.
83 * the list of full states
84 * @param prevFullState
85 * the previous full state, or null
87 void handle(@NonNull List
<List
<ITmfStateInterval
>> fullStates
, @Nullable List
<ITmfStateInterval
> prevFullState
);
90 private class ZoomThreadByTime
extends ZoomThread
{
91 private final @NonNull List
<ITmfStateSystem
> fZoomSSList
;
92 private boolean fClearZoomedLists
;
94 public ZoomThreadByTime(@NonNull List
<ITmfStateSystem
> ssList
, long startTime
, long endTime
, long resolution
, boolean restart
) {
95 super(startTime
, endTime
, resolution
);
97 fClearZoomedLists
= !restart
;
102 final List
<ILinkEvent
> links
= new ArrayList
<>();
103 final List
<IMarkerEvent
> markers
= new ArrayList
<>();
104 if (fClearZoomedLists
) {
107 for (ITmfStateSystem ss
: fZoomSSList
) {
108 List
<TimeGraphEntry
> entryList
= null;
109 synchronized (fSSEntryListMap
) {
110 entryList
= fSSEntryListMap
.get(ss
);
112 if (entryList
!= null) {
113 zoomByTime(ss
, entryList
, links
, markers
, getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
116 if (!getMonitor().isCanceled()) {
117 getTimeGraphViewer().setLinks(links
);
118 /* Refresh the trace-specific markers when zooming */
119 markers
.addAll(getTraceMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
120 getTimeGraphViewer().setMarkers(markers
);
125 public void cancel() {
127 if (fClearZoomedLists
) {
132 private void zoomByTime(final ITmfStateSystem ss
, final List
<TimeGraphEntry
> entryList
, final List
<ILinkEvent
> links
, final List
<IMarkerEvent
> markers
,
133 long startTime
, long endTime
, long resolution
, final @NonNull IProgressMonitor monitor
) {
134 final long start
= Math
.max(startTime
, ss
.getStartTime());
135 final long end
= Math
.min(endTime
, ss
.getCurrentEndTime());
136 final boolean fullRange
= getZoomStartTime() <= getStartTime() && getZoomEndTime() >= getEndTime();
143 queryFullStates(ss
, start
, end
, resolution
, monitor
, new IQueryHandler() {
145 public void handle(@NonNull List
<List
<ITmfStateInterval
>> fullStates
, @Nullable List
<ITmfStateInterval
> prevFullState
) {
147 for (TimeGraphEntry entry
: entryList
) {
148 zoom(checkNotNull(entry
), ss
, fullStates
, prevFullState
, monitor
);
151 /* Refresh the arrows when zooming */
152 links
.addAll(getLinkList(ss
, fullStates
, prevFullState
, monitor
));
153 /* Refresh the view-specific markers when zooming */
154 markers
.addAll(getViewMarkerList(ss
, fullStates
, prevFullState
, monitor
));
160 private void zoom(@NonNull TimeGraphEntry entry
, ITmfStateSystem ss
, @NonNull List
<List
<ITmfStateInterval
>> fullStates
, @Nullable List
<ITmfStateInterval
> prevFullState
, @NonNull IProgressMonitor monitor
) {
161 List
<ITimeEvent
> eventList
= getEventList(entry
, ss
, fullStates
, prevFullState
, monitor
);
162 if (eventList
!= null) {
163 for (ITimeEvent event
: eventList
) {
164 entry
.addZoomedEvent(event
);
167 for (ITimeGraphEntry child
: entry
.getChildren()) {
168 if (monitor
.isCanceled()) {
171 if (child
instanceof TimeGraphEntry
) {
172 zoom((TimeGraphEntry
) child
, ss
, fullStates
, prevFullState
, monitor
);
177 private void clearZoomedLists() {
178 for (ITmfStateSystem ss
: fZoomSSList
) {
179 List
<TimeGraphEntry
> entryList
= null;
180 synchronized (fSSEntryListMap
) {
181 entryList
= fSSEntryListMap
.get(ss
);
183 if (entryList
!= null) {
184 for (TimeGraphEntry entry
: entryList
) {
185 clearZoomedList(entry
);
189 fClearZoomedLists
= false;
192 private void clearZoomedList(TimeGraphEntry entry
) {
193 entry
.setZoomedEventList(null);
194 for (ITimeGraphEntry child
: entry
.getChildren()) {
195 if (child
instanceof TimeGraphEntry
) {
196 clearZoomedList((TimeGraphEntry
) child
);
202 // ------------------------------------------------------------------------
204 // ------------------------------------------------------------------------
207 * Constructs a time graph view that contains either a time graph viewer or
208 * a time graph combo.
210 * By default, the view uses a time graph viewer. To use a time graph combo,
211 * the subclass constructor must call {@link #setTreeColumns(String[])} and
212 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
217 * The presentation provider
219 public AbstractStateSystemTimeGraphView(String id
, TimeGraphPresentationProvider pres
) {
223 // ------------------------------------------------------------------------
225 // ------------------------------------------------------------------------
228 * Gets the entry list for a state system
233 * @return the entry list map
235 protected List
<TimeGraphEntry
> getEntryList(ITmfStateSystem ss
) {
236 synchronized (fSSEntryListMap
) {
237 return fSSEntryListMap
.get(ss
);
242 * Adds a trace entry list to the entry list map
249 * the list of time graph entries
251 protected void putEntryList(ITmfTrace trace
, ITmfStateSystem ss
, List
<TimeGraphEntry
> list
) {
252 super.putEntryList(trace
, list
);
253 synchronized (fSSEntryListMap
) {
254 fSSEntryListMap
.put(ss
, new CopyOnWriteArrayList
<>(list
));
255 fTraceSSMap
.put(trace
, ss
);
260 * Adds a list of entries to a trace's entry list
267 * the list of time graph entries to add
269 protected void addToEntryList(ITmfTrace trace
, ITmfStateSystem ss
, List
<TimeGraphEntry
> list
) {
270 super.addToEntryList(trace
, list
);
271 synchronized (fSSEntryListMap
) {
272 List
<TimeGraphEntry
> entryList
= fSSEntryListMap
.get(ss
);
273 if (entryList
== null) {
274 fSSEntryListMap
.put(ss
, new CopyOnWriteArrayList
<>(list
));
276 entryList
.addAll(list
);
278 fTraceSSMap
.put(trace
, ss
);
283 * Removes a list of entries from a trace's entry list
290 * the list of time graph entries to remove
292 protected void removeFromEntryList(ITmfTrace trace
, ITmfStateSystem ss
, List
<TimeGraphEntry
> list
) {
293 super.removeFromEntryList(trace
, list
);
294 synchronized (fSSEntryListMap
) {
295 List
<TimeGraphEntry
> entryList
= fSSEntryListMap
.get(ss
);
296 if (entryList
!= null) {
297 entryList
.removeAll(list
);
298 if (entryList
.isEmpty()) {
299 fTraceSSMap
.remove(trace
, ss
);
306 protected @Nullable ZoomThread
createZoomThread(long startTime
, long endTime
, long resolution
, boolean restart
) {
307 List
<ITmfStateSystem
> ssList
= null;
308 synchronized (fSSEntryListMap
) {
309 ssList
= new ArrayList
<>(fTraceSSMap
.get(getTrace()));
311 if (ssList
.isEmpty()) {
314 return new ZoomThreadByTime(ssList
, startTime
, endTime
, resolution
, restart
);
318 * Query the state system full state for the given time range.
329 * The progress monitor
333 protected void queryFullStates(ITmfStateSystem ss
, long start
, long end
, long resolution
,
334 @NonNull IProgressMonitor monitor
, @NonNull IQueryHandler handler
) {
335 List
<List
<ITmfStateInterval
>> fullStates
= new ArrayList
<>();
336 List
<ITmfStateInterval
> prevFullState
= null;
340 if (monitor
.isCanceled()) {
343 List
<ITmfStateInterval
> fullState
= ss
.queryFullState(time
);
344 fullStates
.add(fullState
);
345 if (fullStates
.size() * fullState
.size() > MAX_INTERVALS
) {
346 handler
.handle(fullStates
, prevFullState
);
347 prevFullState
= fullStates
.get(fullStates
.size() - 1);
353 time
= Math
.min(end
, time
+ resolution
);
355 if (fullStates
.size() > 0) {
356 handler
.handle(fullStates
, prevFullState
);
358 } catch (StateSystemDisposedException e
) {
364 * Gets the list of events for an entry for a given list of full states.
367 * The time graph entry
371 * A list of full states
372 * @param prevFullState
373 * The previous full state, or null
376 * @return The list of time graph events
378 protected abstract @Nullable List
<ITimeEvent
> getEventList(@NonNull TimeGraphEntry tgentry
, ITmfStateSystem ss
,
379 @NonNull List
<List
<ITmfStateInterval
>> fullStates
, @Nullable List
<ITmfStateInterval
> prevFullState
, @NonNull IProgressMonitor monitor
);
382 * Gets the list of links (displayed as arrows) for a given list of full
383 * states. The default implementation returns an empty list.
388 * A list of full states
389 * @param prevFullState
390 * The previous full state, or null
393 * @return The list of link events
396 protected @NonNull List
<ILinkEvent
> getLinkList(ITmfStateSystem ss
,
397 @NonNull List
<List
<ITmfStateInterval
>> fullStates
, @Nullable List
<ITmfStateInterval
> prevFullState
, @NonNull IProgressMonitor monitor
) {
398 return new ArrayList
<>();
402 * Gets the list of markers for a given list of full
403 * states. The default implementation returns an empty list.
408 * A list of full states
409 * @param prevFullState
410 * The previous full state, or null
413 * @return The list of marker events
416 protected @NonNull List
<IMarkerEvent
> getViewMarkerList(ITmfStateSystem ss
,
417 @NonNull List
<List
<ITmfStateInterval
>> fullStates
, @Nullable List
<ITmfStateInterval
> prevFullState
, @NonNull IProgressMonitor monitor
) {
418 return new ArrayList
<>();
422 * @deprecated The subclass should call {@link #getEntryList(ITmfStateSystem)} instead.
426 protected final List
<TimeGraphEntry
> getEntryList(ITmfTrace trace
) {
427 throw new UnsupportedOperationException();
431 * @deprecated The subclass should call {@link #addToEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
435 protected final void addToEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
436 throw new UnsupportedOperationException();
440 * @deprecated The subclass should call {@link #putEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
444 protected final void putEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
445 throw new UnsupportedOperationException();
449 * @deprecated The subclass should call {@link #removeFromEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
453 protected final void removeFromEntryList(ITmfTrace trace
, List
<TimeGraphEntry
> list
) {
454 throw new UnsupportedOperationException();
458 * @deprecated The subclass should implement {@link #getEventList(TimeGraphEntry, ITmfStateSystem, List, List, IProgressMonitor)} instead.
462 protected final List
<ITimeEvent
> getEventList(TimeGraphEntry entry
, long startTime
, long endTime
, long resolution
, IProgressMonitor monitor
) {
463 throw new UnsupportedOperationException();
467 * @deprecated The subclass should implement {@link #getLinkList(ITmfStateSystem, List, List, IProgressMonitor)} instead.
471 protected final List
<ILinkEvent
> getLinkList(long startTime
, long endTime
, long resolution
, IProgressMonitor monitor
) {
472 throw new UnsupportedOperationException();
476 * @deprecated The subclass should implement {@link #getViewMarkerList(ITmfStateSystem, List, List, IProgressMonitor)} instead.
480 protected final List
<IMarkerEvent
> getViewMarkerList(long startTime
, long endTime
, long resolution
, IProgressMonitor monitor
) {
481 throw new UnsupportedOperationException();
484 // ------------------------------------------------------------------------
486 // ------------------------------------------------------------------------
490 public void traceClosed(final TmfTraceClosedSignal signal
) {
491 super.traceClosed(signal
);
492 synchronized (fSSEntryListMap
) {
493 for (ITmfStateSystem ss
: fTraceSSMap
.removeAll(signal
.getTrace())) {
494 fSSEntryListMap
.remove(ss
);