Commit | Line | Data |
---|---|---|
03c96217 | 1 | /****************************************************************************** |
edded5c1 | 2 | * Copyright (c) 2015, 2016 Ericsson |
03c96217 BH |
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 | * France Lapointe Nguyen - Initial API and implementation | |
11 | * Bernd Hufmann - Extracted abstract class from LatencyScatterGraphViewer | |
12 | *******************************************************************************/ | |
13 | ||
edded5c1 | 14 | package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.scatter; |
03c96217 | 15 | |
21c917fe | 16 | import java.text.Format; |
03c96217 BH |
17 | import java.util.ArrayList; |
18 | import java.util.Collection; | |
19 | import java.util.Collections; | |
20 | import java.util.Iterator; | |
21 | import java.util.List; | |
22 | ||
23 | import org.eclipse.core.runtime.IProgressMonitor; | |
24 | import org.eclipse.core.runtime.IStatus; | |
25 | import org.eclipse.core.runtime.Status; | |
26 | import org.eclipse.core.runtime.jobs.Job; | |
27 | import org.eclipse.jdt.annotation.Nullable; | |
28 | import org.eclipse.swt.graphics.Point; | |
29 | import org.eclipse.swt.widgets.Composite; | |
30 | import org.eclipse.swt.widgets.Display; | |
31 | import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisModule; | |
32 | import org.eclipse.tracecompass.analysis.timing.core.segmentstore.IAnalysisProgressListener; | |
21c917fe | 33 | import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.SubSecondTimeWithUnitFormat; |
03c96217 BH |
34 | import org.eclipse.tracecompass.common.core.NonNullUtils; |
35 | import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator; | |
edded5c1 | 36 | import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter.Messages; |
21c917fe | 37 | import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter.SegmentStoreScatterGraphTooltipProvider; |
03c96217 BH |
38 | import org.eclipse.tracecompass.segmentstore.core.ISegment; |
39 | import org.eclipse.tracecompass.segmentstore.core.ISegmentStore; | |
40 | import org.eclipse.tracecompass.segmentstore.core.SegmentComparators; | |
41 | import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; | |
42 | import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; | |
43 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal; | |
44 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal; | |
45 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal; | |
46 | import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal; | |
47 | import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp; | |
48 | import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange; | |
49 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
50 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; | |
51 | import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo; | |
52 | import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentSignal; | |
53 | import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfChartTimeStampFormat; | |
54 | import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.linecharts.TmfCommonXLineChartViewer; | |
55 | import org.swtchart.Chart; | |
56 | import org.swtchart.IAxis; | |
57 | import org.swtchart.IAxisTick; | |
58 | import org.swtchart.ILineSeries; | |
59 | import org.swtchart.ILineSeries.PlotSymbolType; | |
60 | import org.swtchart.ISeries.SeriesType; | |
61 | import org.swtchart.ISeriesSet; | |
62 | import org.swtchart.LineStyle; | |
63 | import org.swtchart.Range; | |
64 | ||
65 | /** | |
66 | * Displays the segment store analysis data in a scatter graph | |
67 | * | |
68 | * @author France Lapointe Nguyen | |
69 | * @author Matthew Khouzam - reduced memory usage | |
70 | * @since 2.0 | |
71 | */ | |
72 | public abstract class AbstractSegmentStoreScatterGraphViewer extends TmfCommonXLineChartViewer { | |
03c96217 | 73 | |
21c917fe MK |
74 | private static final Format FORMAT = new SubSecondTimeWithUnitFormat(); |
75 | ||
03c96217 BH |
76 | private final class CompactingSegmentStoreQuery extends Job { |
77 | private static final long MAX_POINTS = 1000; | |
78 | private final TmfTimeRange fCurrentRange; | |
79 | ||
80 | private CompactingSegmentStoreQuery(TmfTimeRange currentRange) { | |
81 | super(Messages.SegmentStoreScatterGraphViewer_compactTitle); | |
82 | fCurrentRange = currentRange; | |
83 | } | |
84 | ||
85 | @Override | |
86 | protected IStatus run(@Nullable IProgressMonitor monitor) { | |
87 | final IProgressMonitor statusMonitor = monitor; | |
88 | if (statusMonitor == null) { | |
89 | return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Monitor is null"); //$NON-NLS-1$ | |
90 | } | |
91 | ||
92 | AbstractSegmentStoreAnalysisModule module = getAnalysisModule(); | |
93 | final long startTimeInNanos = getTimeInNanos(fCurrentRange.getStartTime()); | |
94 | final long endTimeInNanos = getTimeInNanos(fCurrentRange.getEndTime()); | |
95 | if (module == null) { | |
96 | setWindowRange(startTimeInNanos, endTimeInNanos); | |
df2597e0 | 97 | redraw(statusMonitor, startTimeInNanos, startTimeInNanos, Collections.EMPTY_LIST); |
03c96217 BH |
98 | return new Status(IStatus.WARNING, Activator.PLUGIN_ID, "Analysis module not available"); //$NON-NLS-1$ |
99 | } | |
100 | ||
101 | final ISegmentStore<ISegment> results = module.getResults(); | |
102 | if (results == null) { | |
103 | setWindowRange(startTimeInNanos, endTimeInNanos); | |
df2597e0 | 104 | redraw(statusMonitor, startTimeInNanos, startTimeInNanos, Collections.EMPTY_LIST); |
03c96217 BH |
105 | return new Status(IStatus.INFO, Activator.PLUGIN_ID, "Analysis module does not have results"); //$NON-NLS-1$ |
106 | } | |
107 | ||
108 | final long startTime = fCurrentRange.getStartTime().getValue(); | |
109 | final long endTime = fCurrentRange.getEndTime().getValue(); | |
110 | fPixelStart = startTime; | |
111 | fPixelSize = (endTime - startTime) / MAX_POINTS; | |
112 | final Iterable<ISegment> intersectingElements = results.getIntersectingElements(startTime, endTime); | |
113 | ||
114 | final List<ISegment> list = convertIterableToList(intersectingElements, statusMonitor); | |
115 | final List<ISegment> displayData = (!list.isEmpty()) ? compactList(startTime, list, statusMonitor) : list; | |
116 | ||
117 | setWindowRange(startTimeInNanos, endTimeInNanos); | |
118 | redraw(statusMonitor, startTime, endTime, displayData); | |
119 | ||
120 | if (statusMonitor.isCanceled()) { | |
121 | return NonNullUtils.checkNotNull(Status.CANCEL_STATUS); | |
122 | } | |
123 | return NonNullUtils.checkNotNull(Status.OK_STATUS); | |
124 | ||
125 | } | |
126 | ||
127 | private void redraw(final IProgressMonitor statusMonitor, final long startTime, final long endTime, final List<ISegment> displayData) { | |
128 | fDisplayData = displayData; | |
129 | Display.getDefault().asyncExec(new Runnable() { | |
130 | ||
131 | @Override | |
132 | public void run() { | |
133 | updateData(startTime, endTime, displayData.size(), statusMonitor); | |
134 | } | |
135 | }); | |
136 | } | |
137 | ||
138 | private List<ISegment> compactList(final long startTime, final List<ISegment> listToCompact, final IProgressMonitor statusMonitor) { | |
139 | List<ISegment> displayData = new ArrayList<>(); | |
140 | ISegment last = listToCompact.get(0); | |
141 | if (last.getStart() >= startTime) { | |
142 | displayData.add(last); | |
143 | } | |
144 | for (ISegment next : listToCompact) { | |
145 | if (next.getStart() < startTime) { | |
146 | continue; | |
147 | } | |
148 | if (statusMonitor.isCanceled()) { | |
df2597e0 | 149 | return Collections.EMPTY_LIST; |
03c96217 BH |
150 | } |
151 | if (!overlaps(last, next)) { | |
152 | displayData.add(next); | |
153 | last = next; | |
154 | } | |
155 | } | |
156 | return displayData; | |
157 | } | |
158 | ||
159 | private List<ISegment> convertIterableToList(final Iterable<ISegment> iterable, final IProgressMonitor statusMonitor) { | |
160 | final List<ISegment> list = new ArrayList<>(); | |
161 | for (ISegment seg : iterable) { | |
162 | if (statusMonitor.isCanceled()) { | |
df2597e0 | 163 | return Collections.EMPTY_LIST; |
03c96217 BH |
164 | } |
165 | list.add(seg); | |
166 | } | |
167 | Collections.sort(list, SegmentComparators.INTERVAL_START_COMPARATOR); | |
168 | return list; | |
169 | } | |
170 | ||
171 | private boolean overlaps(ISegment last, ISegment next) { | |
172 | long timePerPix = fPixelSize; | |
173 | final long start = last.getStart(); | |
174 | final long pixelStart = fPixelStart; | |
175 | final long pixelDuration = start - pixelStart; | |
176 | long startPixBoundL = pixelDuration / timePerPix * timePerPix + pixelStart; | |
177 | long startPixBoundR = startPixBoundL + timePerPix; | |
178 | final long currentStart = next.getStart(); | |
179 | if (currentStart >= startPixBoundL && currentStart <= startPixBoundR) { | |
180 | long length = last.getLength(); | |
181 | long lengthNext = next.getLength(); | |
182 | long lengthLow = length / timePerPix * timePerPix; | |
183 | long lengthHigh = lengthLow + timePerPix; | |
184 | return (lengthNext >= lengthLow && lengthNext <= lengthHigh); | |
185 | } | |
186 | return false; | |
187 | } | |
188 | } | |
189 | ||
190 | // ------------------------------------------------------------------------ | |
191 | // Attributes | |
192 | // ------------------------------------------------------------------------ | |
193 | ||
194 | /** | |
195 | * Listener to update the model with the semgent store analysis results | |
196 | * once the analysis is fully completed | |
197 | */ | |
198 | private final class AnalysisProgressListener implements IAnalysisProgressListener { | |
199 | ||
200 | @Override | |
201 | public void onComplete(AbstractSegmentStoreAnalysisModule activeAnalysis, ISegmentStore<ISegment> results) { | |
202 | // Only update the model if trace that was analyzed is active trace | |
203 | if (activeAnalysis.equals(getAnalysisModule())) { | |
204 | updateModel(results); | |
205 | updateRange(TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange()); | |
206 | } | |
207 | } | |
208 | } | |
209 | ||
210 | private long fPixelSize = -1; | |
211 | ||
212 | private long fPixelStart = 0; | |
213 | /** | |
214 | * Data to display | |
215 | */ | |
df2597e0 | 216 | private Collection<ISegment> fDisplayData = Collections.EMPTY_LIST; |
03c96217 BH |
217 | |
218 | /** | |
219 | * Analysis completion listener | |
220 | */ | |
221 | private AnalysisProgressListener fListener; | |
222 | ||
223 | /** | |
224 | * Current analysis module | |
225 | */ | |
226 | private @Nullable AbstractSegmentStoreAnalysisModule fAnalysisModule; | |
227 | ||
228 | private @Nullable Job fCompactingJob; | |
229 | ||
230 | // ------------------------------------------------------------------------ | |
231 | // Constructor | |
232 | // ------------------------------------------------------------------------ | |
233 | ||
234 | /** | |
235 | * Constructor | |
236 | * | |
237 | * @param parent | |
238 | * parent composite | |
239 | * @param title | |
240 | * name of the graph | |
241 | * @param xLabel | |
242 | * name of the x axis | |
243 | * @param yLabel | |
244 | * name of the y axis | |
245 | */ | |
246 | public AbstractSegmentStoreScatterGraphViewer(Composite parent, String title, String xLabel, String yLabel) { | |
247 | super(parent, title, xLabel, yLabel); | |
a2de198a | 248 | setTooltipProvider(new SegmentStoreScatterGraphTooltipProvider(this)); |
03c96217 BH |
249 | fListener = new AnalysisProgressListener(); |
250 | ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace(); | |
251 | initializeModule(trace); | |
252 | getSwtChart().getLegend().setVisible(false); | |
21c917fe | 253 | getSwtChart().getAxisSet().getYAxis(0).getTick().setFormat(FORMAT); |
03c96217 BH |
254 | } |
255 | ||
256 | private final void initializeModule(@Nullable ITmfTrace trace) { | |
257 | if (trace != null) { | |
258 | final AbstractSegmentStoreAnalysisModule analysisModuleOfClass = getSegmentStoreAnalysisModule(trace); | |
259 | if (analysisModuleOfClass != null) { | |
260 | analysisModuleOfClass.addListener(fListener); | |
261 | setData(analysisModuleOfClass); | |
262 | updateRange(TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange()); | |
263 | } | |
264 | } | |
265 | } | |
266 | ||
267 | // ------------------------------------------------------------------------ | |
268 | // Operations | |
269 | // ------------------------------------------------------------------------ | |
270 | ||
271 | /** | |
272 | * Update the data in the graph | |
273 | * | |
274 | * @param dataInput | |
275 | * new model | |
276 | */ | |
277 | public void updateModel(@Nullable ISegmentStore<ISegment> dataInput) { | |
278 | // Update new window range | |
279 | TmfTimeRange currentRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange(); | |
280 | long currentStart = getTimeInNanos(currentRange.getStartTime()); | |
281 | long currentEnd = getTimeInNanos(currentRange.getEndTime()); | |
282 | if (dataInput == null) { | |
283 | if (!getDisplay().isDisposed()) { | |
284 | Display.getDefault().syncExec(new Runnable() { | |
285 | @Override | |
286 | public void run() { | |
287 | clearContent(); | |
288 | } | |
289 | }); | |
290 | } | |
df2597e0 | 291 | fDisplayData = Collections.EMPTY_LIST; |
03c96217 BH |
292 | } else { |
293 | Collection<ISegment> elements = (Collection<ISegment>) dataInput.getIntersectingElements(currentStart, currentEnd); | |
294 | // getIntersectingElements can return an unsorted iterable, make | |
295 | // sure our collection is sorted | |
296 | ArrayList<ISegment> list = new ArrayList<>(elements); | |
297 | Collections.sort(list, SegmentComparators.INTERVAL_START_COMPARATOR); | |
298 | fDisplayData = list; | |
299 | } | |
300 | setWindowRange(currentStart, currentEnd); | |
301 | updateRange(currentRange); | |
302 | } | |
303 | ||
304 | @Override | |
305 | protected void initializeDataSource() { | |
306 | ITmfTrace trace = getTrace(); | |
307 | initializeModule(trace); | |
308 | if (trace != null) { | |
309 | setData(getSegmentStoreAnalysisModule(trace)); | |
310 | } | |
311 | } | |
312 | ||
313 | @Override | |
314 | protected void updateData(final long start, final long end, int nb, @Nullable IProgressMonitor monitor) { | |
315 | // Third parameter is not used by implementation | |
316 | // Determine data that needs to be visible | |
317 | Collection<ISegment> data = fDisplayData; | |
318 | ||
319 | final int dataSize = (nb == 0) ? data.size() : nb; | |
320 | if (dataSize == 0 || end == start) { | |
321 | return; | |
322 | } | |
323 | ||
324 | final double[] xSeries = new double[dataSize]; | |
325 | final double[] ySeries = new double[dataSize]; | |
326 | // For each visible segments, add start time to x value and duration | |
327 | // for y value | |
328 | Iterator<ISegment> modelIter = data.iterator(); | |
329 | long maxTempY = 1; | |
330 | for (int i = 0; i < dataSize; i++) { | |
331 | if (modelIter.hasNext()) { | |
332 | ISegment segment = modelIter.next(); | |
333 | xSeries[i] = segment.getStart() - start; | |
334 | ySeries[i] = segment.getLength(); | |
335 | maxTempY = Math.max(maxTempY, segment.getLength()); | |
336 | } | |
337 | } | |
338 | final long maxY = maxTempY; | |
339 | setXAxis(xSeries); | |
340 | final Chart swtChart = getSwtChart(); | |
341 | if (swtChart.isDisposed() || xSeries.length < 1) { | |
342 | return; | |
343 | } | |
344 | swtChart.updateLayout(); | |
345 | setSeries(Messages.SegmentStoreScatterGraphViewer_legend, ySeries); // $NON-NLS-1$ | |
346 | final TmfChartTimeStampFormat tmfChartTimeStampFormat = new TmfChartTimeStampFormat(getTimeOffset()); | |
347 | ILineSeries series = (ILineSeries) swtChart.getSeriesSet().getSeries(Messages.SegmentStoreScatterGraphViewer_legend); | |
348 | if (series == null) { | |
349 | series = addSeries(Messages.SegmentStoreScatterGraphViewer_legend); | |
350 | } | |
351 | series.setXSeries(xSeries); | |
352 | /* Find the minimal and maximum values in this series */ | |
353 | series.setYSeries(ySeries); | |
354 | ||
355 | final IAxis xAxis = swtChart.getAxisSet().getXAxis(0); | |
356 | IAxisTick xTick = xAxis.getTick(); | |
357 | xTick.setFormat(tmfChartTimeStampFormat); | |
358 | xAxis.setRange(new Range(0.0, end - start)); | |
359 | if (maxY > 0.0) { | |
360 | swtChart.getAxisSet().getYAxis(0).setRange(new Range(0.0, maxY)); | |
361 | } | |
362 | swtChart.redraw(); | |
363 | ||
364 | if (isSendTimeAlignSignals()) { | |
365 | // The width of the chart might have changed and its | |
366 | // time axis might be misaligned with the other views | |
367 | Point viewPos = AbstractSegmentStoreScatterGraphViewer.this.getParent().getParent().toDisplay(0, 0); | |
368 | int axisPos = swtChart.toDisplay(0, 0).x + getPointAreaOffset(); | |
369 | int timeAxisOffset = axisPos - viewPos.x; | |
370 | TmfTimeViewAlignmentInfo timeAlignmentInfo = new TmfTimeViewAlignmentInfo(getControl().getShell(), viewPos, timeAxisOffset); | |
371 | TmfSignalManager.dispatchSignal(new TmfTimeViewAlignmentSignal(AbstractSegmentStoreScatterGraphViewer.this, timeAlignmentInfo, true)); | |
372 | } | |
373 | } | |
374 | ||
375 | @Override | |
376 | protected void setWindowRange(final long windowStartTime, final long windowEndTime) { | |
377 | super.setWindowRange(windowStartTime, windowEndTime); | |
378 | } | |
379 | ||
380 | @Override | |
381 | protected ILineSeries addSeries(@Nullable String seriesName) { | |
382 | ISeriesSet seriesSet = getSwtChart().getSeriesSet(); | |
383 | ILineSeries series = (ILineSeries) seriesSet.createSeries(SeriesType.LINE, seriesName); | |
384 | series.setVisible(true); | |
385 | series.enableArea(false); | |
386 | series.setLineStyle(LineStyle.NONE); | |
387 | series.setSymbolType(PlotSymbolType.DIAMOND); | |
388 | return series; | |
389 | } | |
390 | ||
391 | /** | |
392 | * Set the data into the viewer. Will update model is analysis is completed | |
393 | * or run analysis if not completed | |
394 | * | |
395 | * @param analysis | |
396 | * Segment store analysis module | |
397 | */ | |
398 | public void setData(@Nullable AbstractSegmentStoreAnalysisModule analysis) { | |
399 | if (analysis == null) { | |
400 | updateModel(null); | |
401 | return; | |
402 | } | |
403 | ISegmentStore<ISegment> results = analysis.getResults(); | |
404 | // If results are not null, then analysis is completed and model can be | |
405 | // updated | |
406 | if (results != null) { | |
407 | updateModel(results); | |
408 | setAnalysisModule(analysis); | |
409 | return; | |
410 | } | |
411 | updateModel(null); | |
412 | analysis.addListener(fListener); | |
413 | analysis.schedule(); | |
414 | setAnalysisModule(analysis); | |
415 | } | |
416 | ||
417 | /** | |
418 | * Returns the segment store analysis module | |
df2597e0 | 419 | * |
03c96217 BH |
420 | * @param trace |
421 | * The trace to consider | |
422 | * @return the analysis module | |
423 | */ | |
424 | protected @Nullable abstract AbstractSegmentStoreAnalysisModule getSegmentStoreAnalysisModule(ITmfTrace trace); | |
425 | ||
03c96217 BH |
426 | // ------------------------------------------------------------------------ |
427 | // Signal handlers | |
428 | // ------------------------------------------------------------------------ | |
429 | ||
430 | /** | |
431 | * @param signal | |
432 | * Signal received when a different trace is selected | |
433 | */ | |
434 | @Override | |
435 | @TmfSignalHandler | |
436 | public void traceSelected(@Nullable TmfTraceSelectedSignal signal) { | |
437 | super.traceSelected(signal); | |
438 | if (signal == null) { | |
439 | return; | |
440 | } | |
441 | ITmfTrace trace = signal.getTrace(); | |
442 | setTrace(trace); | |
443 | if (trace != null) { | |
444 | final TmfTimeRange timeRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange(); | |
445 | setWindowRange( | |
446 | timeRange.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(), | |
447 | timeRange.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue()); | |
448 | setData(getSegmentStoreAnalysisModule(trace)); | |
449 | updateRange(timeRange); | |
450 | } | |
451 | } | |
452 | ||
453 | /** | |
454 | * @param signal | |
455 | * Signal received when trace is opened | |
456 | */ | |
457 | @Override | |
458 | @TmfSignalHandler | |
459 | public void traceOpened(@Nullable TmfTraceOpenedSignal signal) { | |
460 | super.traceOpened(signal); | |
461 | if (signal == null) { | |
462 | return; | |
463 | } | |
464 | ITmfTrace trace = signal.getTrace(); | |
465 | setTrace(trace); | |
466 | if (trace != null) { | |
467 | ||
468 | final AbstractSegmentStoreAnalysisModule analysisModuleOfClass = getSegmentStoreAnalysisModule(trace); | |
469 | final TmfTimeRange timeRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange(); | |
470 | setWindowRange( | |
471 | getTimeInNanos(timeRange.getStartTime()), | |
472 | getTimeInNanos(timeRange.getEndTime())); | |
473 | setData(analysisModuleOfClass); | |
474 | } | |
475 | ||
476 | } | |
477 | ||
478 | private void updateRange(final @Nullable TmfTimeRange timeRange) { | |
479 | Job compactingJob = fCompactingJob; | |
480 | if (compactingJob != null && compactingJob.getState() == Job.RUNNING) { | |
481 | compactingJob.cancel(); | |
482 | } | |
483 | compactingJob = new CompactingSegmentStoreQuery(NonNullUtils.checkNotNull(timeRange)); | |
484 | fCompactingJob = compactingJob; | |
485 | compactingJob.schedule(); | |
486 | } | |
487 | ||
488 | /** | |
489 | * @param signal | |
490 | * Signal received when last opened trace is closed | |
491 | */ | |
492 | @Override | |
493 | @TmfSignalHandler | |
494 | public void traceClosed(@Nullable TmfTraceClosedSignal signal) { | |
495 | super.traceClosed(signal); | |
496 | if (signal != null) { | |
497 | // Check if there is no more opened trace | |
498 | if (TmfTraceManager.getInstance().getActiveTrace() == null) { | |
499 | AbstractSegmentStoreAnalysisModule analysis = getAnalysisModule(); | |
500 | if (analysis != null) { | |
76be6c00 | 501 | analysis.removeListener(fListener); |
03c96217 BH |
502 | } |
503 | clearContent(); | |
504 | } | |
505 | } | |
506 | refresh(); | |
507 | } | |
508 | ||
509 | /** | |
510 | * @param signal | |
511 | * Signal received when window range is updated | |
512 | */ | |
513 | @Override | |
514 | @TmfSignalHandler | |
515 | public void windowRangeUpdated(@Nullable TmfWindowRangeUpdatedSignal signal) { | |
516 | super.windowRangeUpdated(signal); | |
517 | if (signal == null) { | |
518 | return; | |
519 | } | |
520 | if (getTrace() != null) { | |
521 | final TmfTimeRange currentRange = signal.getCurrentRange(); | |
522 | updateRange(currentRange); | |
523 | } else { | |
524 | Activator.getDefault().logInfo("No Trace to update"); //$NON-NLS-1$ | |
525 | } | |
526 | } | |
527 | ||
528 | private @Nullable AbstractSegmentStoreAnalysisModule getAnalysisModule() { | |
529 | return fAnalysisModule; | |
530 | } | |
531 | ||
532 | private void setAnalysisModule(AbstractSegmentStoreAnalysisModule analysisModule) { | |
533 | fAnalysisModule = analysisModule; | |
534 | } | |
535 | ||
536 | private static long getTimeInNanos(final ITmfTimestamp currentTime) { | |
537 | return currentTime.normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); | |
538 | } | |
539 | } |