tmf: Update AbstractTimeGraphView and TimeGraphEntry API
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / timegraph / AbstractStateSystemTimeGraphView.java
CommitLineData
6ae6c5bd 1/*******************************************************************************
f8f46a52 2 * Copyright (c) 2015, 2016 Ericsson
6ae6c5bd
PT
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
13package org.eclipse.tracecompass.tmf.ui.views.timegraph;
14
15import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
17import java.util.ArrayList;
18import java.util.HashMap;
19import java.util.List;
20import java.util.Map;
21import java.util.concurrent.CopyOnWriteArrayList;
22
23import org.eclipse.core.runtime.IProgressMonitor;
24import org.eclipse.jdt.annotation.NonNull;
25import org.eclipse.jdt.annotation.Nullable;
26import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
27import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
28import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
29import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
30import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
31import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
32import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
33import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
e790b877 34import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.IMarkerEvent;
6ae6c5bd 35import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
6ae6c5bd
PT
36import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
37
38import com.google.common.collect.HashMultimap;
39import com.google.common.collect.Multimap;
40
41/**
42 * An abstract time graph view where each entry's time event list is populated
43 * from a state system. The state system full state is queried in chronological
44 * order before creating the time event lists as this is optimal for state
45 * system queries.
46 *
0336f981 47 * @since 1.1
6ae6c5bd
PT
48 */
49public abstract class AbstractStateSystemTimeGraphView extends AbstractTimeGraphView {
50
51 // ------------------------------------------------------------------------
52 // Constants
53 // ------------------------------------------------------------------------
54
55 private static final long MAX_INTERVALS = 1000000;
56
57 // ------------------------------------------------------------------------
58 // Fields
59 // ------------------------------------------------------------------------
60
61 /** The state system to entry list hash map */
62 private final Map<ITmfStateSystem, List<TimeGraphEntry>> fSSEntryListMap = new HashMap<>();
63
64 /** The trace to state system multi map */
65 private final Multimap<ITmfTrace, ITmfStateSystem> fTraceSSMap = HashMultimap.create();
66
67 // ------------------------------------------------------------------------
68 // Classes
69 // ------------------------------------------------------------------------
70
71 /**
72 * Handler for state system queries
73 */
74 public interface IQueryHandler {
75 /**
76 * Handle a full or partial list of full states. This can be called many
77 * times for the same query if the query result is split, in which case
78 * the previous full state is null only the first time it is called, and
79 * set to the last full state of the previous call from then on.
80 *
81 * @param fullStates
82 * the list of full states
83 * @param prevFullState
84 * the previous full state, or null
85 */
86 void handle(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState);
87 }
88
89 private class ZoomThreadByTime extends ZoomThread {
90 private final @NonNull List<ITmfStateSystem> fZoomSSList;
91 private boolean fClearZoomedLists;
92
93 public ZoomThreadByTime(@NonNull List<ITmfStateSystem> ssList, long startTime, long endTime, long resolution, boolean restart) {
94 super(startTime, endTime, resolution);
95 fZoomSSList = ssList;
96 fClearZoomedLists = !restart;
97 }
98
99 @Override
156e9ead 100 public void doRun() {
6ae6c5bd 101 final List<ILinkEvent> links = new ArrayList<>();
e790b877 102 final List<IMarkerEvent> markers = new ArrayList<>();
6ae6c5bd
PT
103 if (fClearZoomedLists) {
104 clearZoomedLists();
105 }
106 for (ITmfStateSystem ss : fZoomSSList) {
107 List<TimeGraphEntry> entryList = null;
108 synchronized (fSSEntryListMap) {
109 entryList = fSSEntryListMap.get(ss);
110 }
111 if (entryList != null) {
e790b877 112 zoomByTime(ss, entryList, links, markers, getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor());
6ae6c5bd
PT
113 }
114 }
115 if (!getMonitor().isCanceled()) {
24333461
PT
116 /* Refresh the trace-specific markers when zooming */
117 markers.addAll(getTraceMarkerList(getZoomStartTime(), getZoomEndTime(), getResolution(), getMonitor()));
6d28f3e8
MAL
118 applyResults(() -> {
119 getTimeGraphViewer().setLinks(links);
120 getTimeGraphViewer().setMarkers(markers);
121 });
6ae6c5bd
PT
122 }
123 }
124
125 @Override
126 public void cancel() {
127 super.cancel();
128 if (fClearZoomedLists) {
129 clearZoomedLists();
130 }
131 }
132
e790b877 133 private void zoomByTime(final ITmfStateSystem ss, final List<TimeGraphEntry> entryList, final List<ILinkEvent> links, final List<IMarkerEvent> markers,
6ae6c5bd
PT
134 long startTime, long endTime, long resolution, final @NonNull IProgressMonitor monitor) {
135 final long start = Math.max(startTime, ss.getStartTime());
136 final long end = Math.min(endTime, ss.getCurrentEndTime());
137 final boolean fullRange = getZoomStartTime() <= getStartTime() && getZoomEndTime() >= getEndTime();
138 if (end < start) {
139 return;
140 }
141 if (fullRange) {
142 redraw();
143 }
144 queryFullStates(ss, start, end, resolution, monitor, new IQueryHandler() {
145 @Override
146 public void handle(@NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState) {
147 if (!fullRange) {
148 for (TimeGraphEntry entry : entryList) {
149 zoom(checkNotNull(entry), ss, fullStates, prevFullState, monitor);
150 }
151 }
152 /* Refresh the arrows when zooming */
143217ee 153 links.addAll(getLinkList(ss, fullStates, prevFullState, monitor));
24333461
PT
154 /* Refresh the view-specific markers when zooming */
155 markers.addAll(getViewMarkerList(ss, fullStates, prevFullState, monitor));
6ae6c5bd
PT
156 }
157 });
158 refresh();
159 }
160
161 private void zoom(@NonNull TimeGraphEntry entry, ITmfStateSystem ss, @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
162 List<ITimeEvent> eventList = getEventList(entry, ss, fullStates, prevFullState, monitor);
163 if (eventList != null) {
6d28f3e8
MAL
164 applyResults(() -> {
165 for (ITimeEvent event : eventList) {
166 if (monitor.isCanceled()) {
167 return;
168 }
169 entry.addZoomedEvent(event);
170 }
171 });
6ae6c5bd 172 }
f8f46a52 173 for (TimeGraphEntry child : entry.getChildren()) {
6ae6c5bd
PT
174 if (monitor.isCanceled()) {
175 return;
176 }
f8f46a52 177 zoom(child, ss, fullStates, prevFullState, monitor);
6ae6c5bd
PT
178 }
179 }
180
181 private void clearZoomedLists() {
182 for (ITmfStateSystem ss : fZoomSSList) {
183 List<TimeGraphEntry> entryList = null;
184 synchronized (fSSEntryListMap) {
185 entryList = fSSEntryListMap.get(ss);
186 }
187 if (entryList != null) {
188 for (TimeGraphEntry entry : entryList) {
189 clearZoomedList(entry);
190 }
191 }
192 }
193 fClearZoomedLists = false;
194 }
195
196 private void clearZoomedList(TimeGraphEntry entry) {
197 entry.setZoomedEventList(null);
f8f46a52
PT
198 for (TimeGraphEntry child : entry.getChildren()) {
199 clearZoomedList(child);
6ae6c5bd
PT
200 }
201 }
202 }
203
204 // ------------------------------------------------------------------------
205 // Constructors
206 // ------------------------------------------------------------------------
207
208 /**
209 * Constructs a time graph view that contains either a time graph viewer or
210 * a time graph combo.
211 *
212 * By default, the view uses a time graph viewer. To use a time graph combo,
213 * the subclass constructor must call {@link #setTreeColumns(String[])} and
214 * {@link #setTreeLabelProvider(TreeLabelProvider)}.
215 *
216 * @param id
217 * The id of the view
218 * @param pres
219 * The presentation provider
220 */
221 public AbstractStateSystemTimeGraphView(String id, TimeGraphPresentationProvider pres) {
222 super(id, pres);
223 }
224
225 // ------------------------------------------------------------------------
226 // Internal
227 // ------------------------------------------------------------------------
228
229 /**
230 * Gets the entry list for a state system
231 *
232 * @param ss
233 * the state system
234 *
235 * @return the entry list map
236 */
237 protected List<TimeGraphEntry> getEntryList(ITmfStateSystem ss) {
238 synchronized (fSSEntryListMap) {
239 return fSSEntryListMap.get(ss);
240 }
241 }
242
243 /**
244 * Adds a trace entry list to the entry list map
245 *
246 * @param trace
247 * the trace
248 * @param ss
249 * the state system
250 * @param list
251 * the list of time graph entries
252 */
253 protected void putEntryList(ITmfTrace trace, ITmfStateSystem ss, List<TimeGraphEntry> list) {
254 super.putEntryList(trace, list);
255 synchronized (fSSEntryListMap) {
256 fSSEntryListMap.put(ss, new CopyOnWriteArrayList<>(list));
257 fTraceSSMap.put(trace, ss);
258 }
259 }
260
261 /**
262 * Adds a list of entries to a trace's entry list
263 *
264 * @param trace
265 * the trace
266 * @param ss
267 * the state system
268 * @param list
269 * the list of time graph entries to add
270 */
271 protected void addToEntryList(ITmfTrace trace, ITmfStateSystem ss, List<TimeGraphEntry> list) {
272 super.addToEntryList(trace, list);
273 synchronized (fSSEntryListMap) {
274 List<TimeGraphEntry> entryList = fSSEntryListMap.get(ss);
275 if (entryList == null) {
276 fSSEntryListMap.put(ss, new CopyOnWriteArrayList<>(list));
277 } else {
278 entryList.addAll(list);
279 }
280 fTraceSSMap.put(trace, ss);
281 }
282 }
283
284 /**
285 * Removes a list of entries from a trace's entry list
286 *
287 * @param trace
288 * the trace
289 * @param ss
290 * the state system
291 * @param list
292 * the list of time graph entries to remove
293 */
294 protected void removeFromEntryList(ITmfTrace trace, ITmfStateSystem ss, List<TimeGraphEntry> list) {
295 super.removeFromEntryList(trace, list);
296 synchronized (fSSEntryListMap) {
297 List<TimeGraphEntry> entryList = fSSEntryListMap.get(ss);
298 if (entryList != null) {
299 entryList.removeAll(list);
300 if (entryList.isEmpty()) {
301 fTraceSSMap.remove(trace, ss);
302 }
303 }
304 }
305 }
306
307 @Override
308 protected @Nullable ZoomThread createZoomThread(long startTime, long endTime, long resolution, boolean restart) {
309 List<ITmfStateSystem> ssList = null;
310 synchronized (fSSEntryListMap) {
311 ssList = new ArrayList<>(fTraceSSMap.get(getTrace()));
312 }
313 if (ssList.isEmpty()) {
314 return null;
315 }
316 return new ZoomThreadByTime(ssList, startTime, endTime, resolution, restart);
317 }
318
319 /**
320 * Query the state system full state for the given time range.
321 *
322 * @param ss
323 * The state system
324 * @param start
325 * The start time
326 * @param end
327 * The end time
328 * @param resolution
329 * The resolution
330 * @param monitor
331 * The progress monitor
332 * @param handler
333 * The query handler
334 */
335 protected void queryFullStates(ITmfStateSystem ss, long start, long end, long resolution,
336 @NonNull IProgressMonitor monitor, @NonNull IQueryHandler handler) {
337 List<List<ITmfStateInterval>> fullStates = new ArrayList<>();
338 List<ITmfStateInterval> prevFullState = null;
339 try {
340 long time = start;
341 while (true) {
342 if (monitor.isCanceled()) {
343 break;
344 }
345 List<ITmfStateInterval> fullState = ss.queryFullState(time);
346 fullStates.add(fullState);
347 if (fullStates.size() * fullState.size() > MAX_INTERVALS) {
348 handler.handle(fullStates, prevFullState);
349 prevFullState = fullStates.get(fullStates.size() - 1);
350 fullStates.clear();
351 }
352 if (time >= end) {
353 break;
354 }
355 time = Math.min(end, time + resolution);
356 }
357 if (fullStates.size() > 0) {
358 handler.handle(fullStates, prevFullState);
359 }
360 } catch (StateSystemDisposedException e) {
361 /* Ignored */
362 }
363 }
364
365 /**
366 * Gets the list of events for an entry for a given list of full states.
f8f46a52
PT
367 * <p>
368 * Called from the ZoomThread for every entry to update the zoomed event
369 * list. Can be an empty implementation if the view does not support zoomed
370 * event lists. Can also be used to compute the full event list.
6ae6c5bd
PT
371 *
372 * @param tgentry
373 * The time graph entry
374 * @param ss
375 * The state system
376 * @param fullStates
377 * A list of full states
378 * @param prevFullState
379 * The previous full state, or null
380 * @param monitor
381 * A progress monitor
382 * @return The list of time graph events
6ae6c5bd
PT
383 */
384 protected abstract @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry tgentry, ITmfStateSystem ss,
385 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor);
386
387 /**
388 * Gets the list of links (displayed as arrows) for a given list of full
389 * states. The default implementation returns an empty list.
390 *
391 * @param ss
392 * The state system
393 * @param fullStates
394 * A list of full states
143217ee
PT
395 * @param prevFullState
396 * The previous full state, or null
6ae6c5bd
PT
397 * @param monitor
398 * A progress monitor
399 * @return The list of link events
143217ee 400 * @since 2.0
6ae6c5bd
PT
401 */
402 protected @NonNull List<ILinkEvent> getLinkList(ITmfStateSystem ss,
143217ee 403 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
6ae6c5bd
PT
404 return new ArrayList<>();
405 }
406
e790b877
PT
407 /**
408 * Gets the list of markers for a given list of full
409 * states. The default implementation returns an empty list.
410 *
411 * @param ss
412 * The state system
413 * @param fullStates
414 * A list of full states
143217ee
PT
415 * @param prevFullState
416 * The previous full state, or null
e790b877
PT
417 * @param monitor
418 * A progress monitor
419 * @return The list of marker events
5dd0ebfe 420 * @since 2.0
e790b877 421 */
24333461 422 protected @NonNull List<IMarkerEvent> getViewMarkerList(ITmfStateSystem ss,
143217ee 423 @NonNull List<List<ITmfStateInterval>> fullStates, @Nullable List<ITmfStateInterval> prevFullState, @NonNull IProgressMonitor monitor) {
e790b877
PT
424 return new ArrayList<>();
425 }
426
6ae6c5bd
PT
427 /**
428 * @deprecated The subclass should call {@link #getEntryList(ITmfStateSystem)} instead.
429 */
430 @Deprecated
431 @Override
432 protected final List<TimeGraphEntry> getEntryList(ITmfTrace trace) {
433 throw new UnsupportedOperationException();
434 }
435
436 /**
437 * @deprecated The subclass should call {@link #addToEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
438 */
439 @Deprecated
440 @Override
441 protected final void addToEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
442 throw new UnsupportedOperationException();
443 }
444
445 /**
446 * @deprecated The subclass should call {@link #putEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
447 */
448 @Deprecated
449 @Override
450 protected final void putEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
451 throw new UnsupportedOperationException();
452 }
453
454 /**
455 * @deprecated The subclass should call {@link #removeFromEntryList(ITmfTrace, ITmfStateSystem, List)} instead.
456 */
457 @Deprecated
458 @Override
459 protected final void removeFromEntryList(ITmfTrace trace, List<TimeGraphEntry> list) {
460 throw new UnsupportedOperationException();
461 }
462
463 /**
464 * @deprecated The subclass should implement {@link #getEventList(TimeGraphEntry, ITmfStateSystem, List, List, IProgressMonitor)} instead.
465 */
466 @Deprecated
467 @Override
468 protected final List<ITimeEvent> getEventList(TimeGraphEntry entry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
469 throw new UnsupportedOperationException();
470 }
471
472 /**
143217ee 473 * @deprecated The subclass should implement {@link #getLinkList(ITmfStateSystem, List, List, IProgressMonitor)} instead.
6ae6c5bd
PT
474 */
475 @Deprecated
476 @Override
477 protected final List<ILinkEvent> getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
478 throw new UnsupportedOperationException();
479 }
480
e790b877 481 /**
24333461 482 * @deprecated The subclass should implement {@link #getViewMarkerList(ITmfStateSystem, List, List, IProgressMonitor)} instead.
e790b877
PT
483 */
484 @Deprecated
485 @Override
24333461 486 protected final List<IMarkerEvent> getViewMarkerList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
e790b877
PT
487 throw new UnsupportedOperationException();
488 }
489
6ae6c5bd
PT
490 // ------------------------------------------------------------------------
491 // Signal handlers
492 // ------------------------------------------------------------------------
493
494 @TmfSignalHandler
495 @Override
496 public void traceClosed(final TmfTraceClosedSignal signal) {
497 super.traceClosed(signal);
498 synchronized (fSSEntryListMap) {
499 for (ITmfStateSystem ss : fTraceSSMap.removeAll(signal.getTrace())) {
500 fSSEntryListMap.remove(ss);
501 }
502 }
503 }
504}
This page took 0.056528 seconds and 5 git commands to generate.