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