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