| 1 | /****************************************************************************** |
| 2 | * Copyright (c) 2015, 2016 Ericsson |
| 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 | |
| 14 | package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.scatter; |
| 15 | |
| 16 | import java.text.Format; |
| 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; |
| 33 | import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.SubSecondTimeWithUnitFormat; |
| 34 | import org.eclipse.tracecompass.common.core.NonNullUtils; |
| 35 | import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator; |
| 36 | import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter.Messages; |
| 37 | import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter.SegmentStoreScatterGraphTooltipProvider; |
| 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 { |
| 73 | |
| 74 | private static final Format FORMAT = new SubSecondTimeWithUnitFormat(); |
| 75 | |
| 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); |
| 97 | redraw(statusMonitor, startTimeInNanos, startTimeInNanos, Collections.EMPTY_LIST); |
| 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); |
| 104 | redraw(statusMonitor, startTimeInNanos, startTimeInNanos, Collections.EMPTY_LIST); |
| 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()) { |
| 149 | return Collections.EMPTY_LIST; |
| 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()) { |
| 163 | return Collections.EMPTY_LIST; |
| 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 | */ |
| 216 | private Collection<ISegment> fDisplayData = Collections.EMPTY_LIST; |
| 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); |
| 248 | setTooltipProvider(new SegmentStoreScatterGraphTooltipProvider(this)); |
| 249 | fListener = new AnalysisProgressListener(); |
| 250 | ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace(); |
| 251 | initializeModule(trace); |
| 252 | getSwtChart().getLegend().setVisible(false); |
| 253 | getSwtChart().getAxisSet().getYAxis(0).getTick().setFormat(FORMAT); |
| 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 | } |
| 291 | fDisplayData = Collections.EMPTY_LIST; |
| 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 |
| 419 | * |
| 420 | * @param trace |
| 421 | * The trace to consider |
| 422 | * @return the analysis module |
| 423 | */ |
| 424 | protected @Nullable abstract AbstractSegmentStoreAnalysisModule getSegmentStoreAnalysisModule(ITmfTrace trace); |
| 425 | |
| 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) { |
| 501 | analysis.removeListener(fListener); |
| 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 | } |