tmf : add a mipmap section in the developer guide
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / trace / TmfExperiment.java
... / ...
CommitLineData
1/*******************************************************************************
2 * Copyright (c) 2009, 2013 Ericsson, École Polytechnique de Montréal
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 * Francois Chouinard - Initial API and implementation
11 * Francois Chouinard - Updated as per TMF Trace Model 1.0
12 * Patrick Tasse - Updated for removal of context clone
13 * Patrick Tasse - Updated for ranks in experiment location
14 * Geneviève Bastien - Added support of experiment synchronization
15 *******************************************************************************/
16
17package org.eclipse.linuxtools.tmf.core.trace;
18
19import java.io.File;
20
21import org.eclipse.core.resources.IFile;
22import org.eclipse.core.resources.IProject;
23import org.eclipse.core.resources.IResource;
24import org.eclipse.core.runtime.CoreException;
25import org.eclipse.core.runtime.IStatus;
26import org.eclipse.core.runtime.Status;
27import org.eclipse.linuxtools.internal.tmf.core.Activator;
28import org.eclipse.linuxtools.internal.tmf.core.trace.TmfExperimentContext;
29import org.eclipse.linuxtools.internal.tmf.core.trace.TmfExperimentLocation;
30import org.eclipse.linuxtools.internal.tmf.core.trace.TmfLocationArray;
31import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
32import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
33import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
34import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
35import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
36import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
37import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
38import org.eclipse.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal;
39import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSynchronizedSignal;
40import org.eclipse.linuxtools.tmf.core.synchronization.SynchronizationAlgorithm;
41import org.eclipse.linuxtools.tmf.core.synchronization.SynchronizationManager;
42import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
43import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
44import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
45import org.eclipse.linuxtools.tmf.core.trace.indexer.checkpoint.TmfCheckpointIndexer;
46import org.eclipse.linuxtools.tmf.core.trace.location.ITmfLocation;
47
48/**
49 * TmfExperiment presents a time-ordered, unified view of a set of ITmfTrace:s
50 * that are part of a tracing experiment.
51 *
52 * @version 1.0
53 * @author Francois Chouinard
54 */
55public class TmfExperiment extends TmfTrace implements ITmfEventParser {
56
57 // ------------------------------------------------------------------------
58 // Constants
59 // ------------------------------------------------------------------------
60
61 /**
62 * The file name of the Synchronization
63 *
64 * @since 3.0
65 */
66 public final static String SYNCHRONIZATION_FILE_NAME = "synchronization.bin"; //$NON-NLS-1$
67
68 /**
69 * The default index page size
70 */
71 public static final int DEFAULT_INDEX_PAGE_SIZE = 5000;
72
73 // ------------------------------------------------------------------------
74 // Attributes
75 // ------------------------------------------------------------------------
76
77 /**
78 * The set of traces that constitute the experiment
79 */
80 protected ITmfTrace[] fTraces;
81
82 /**
83 * The set of traces that constitute the experiment
84 */
85 private boolean fInitialized = false;
86
87 /**
88 * The experiment bookmarks file
89 */
90 private IFile fBookmarksFile;
91
92 // ------------------------------------------------------------------------
93 // Construction
94 // ------------------------------------------------------------------------
95
96 /**
97 * @param type
98 * the event type
99 * @param id
100 * the experiment id
101 * @param traces
102 * the experiment set of traces
103 */
104 public TmfExperiment(final Class<? extends ITmfEvent> type, final String id, final ITmfTrace[] traces) {
105 this(type, id, traces, DEFAULT_INDEX_PAGE_SIZE, null);
106 }
107
108 /**
109 * Constructor of experiment taking type, path, traces and resource
110 *
111 * @param type
112 * the event type
113 * @param id
114 * the experiment id
115 * @param traces
116 * the experiment set of traces
117 * @param resource
118 * the resource associated to the experiment
119 */
120 public TmfExperiment(final Class<? extends ITmfEvent> type, final String id, final ITmfTrace[] traces, IResource resource) {
121 this(type, id, traces, DEFAULT_INDEX_PAGE_SIZE, resource);
122 }
123
124 /**
125 * @param type
126 * the event type
127 * @param path
128 * the experiment path
129 * @param traces
130 * the experiment set of traces
131 * @param indexPageSize
132 * the experiment index page size
133 */
134 public TmfExperiment(final Class<? extends ITmfEvent> type, final String path, final ITmfTrace[] traces, final int indexPageSize) {
135 this(type, path, traces, indexPageSize, null);
136 }
137
138 /**
139 * Full constructor of an experiment, taking the type, path, traces,
140 * indexPageSize and resource
141 *
142 * @param type
143 * the event type
144 * @param path
145 * the experiment path
146 * @param traces
147 * the experiment set of traces
148 * @param indexPageSize
149 * the experiment index page size
150 * @param resource
151 * the resource associated to the experiment
152 */
153 public TmfExperiment(final Class<? extends ITmfEvent> type, final String path, final ITmfTrace[] traces, final int indexPageSize, IResource resource) {
154 setCacheSize(indexPageSize);
155 setStreamingInterval(0);
156 setIndexer(new TmfCheckpointIndexer(this, indexPageSize));
157 setParser(this);
158 try {
159 super.initialize(resource, path, type);
160 } catch (TmfTraceException e) {
161 e.printStackTrace();
162 }
163
164 fTraces = traces;
165
166 if (resource != null) {
167 try {
168 this.synchronizeTraces();
169 } catch (TmfTraceException e) {
170 Activator.logError("Error synchronizing experiment", e); //$NON-NLS-1$
171 }
172 }
173 }
174
175 /**
176 * Clears the experiment
177 */
178 @Override
179 public synchronized void dispose() {
180
181 // Clean up the index if applicable
182 if (getIndexer() != null) {
183 getIndexer().dispose();
184 }
185
186 if (fTraces != null) {
187 for (final ITmfTrace trace : fTraces) {
188 trace.dispose();
189 }
190 fTraces = null;
191 }
192 super.dispose();
193 }
194
195 // ------------------------------------------------------------------------
196 // ITmfTrace - Initializers
197 // ------------------------------------------------------------------------
198
199 @Override
200 public void initTrace(final IResource resource, final String path, final Class<? extends ITmfEvent> type) {
201 }
202
203 /**
204 * @since 2.0
205 */
206 @Override
207 public IStatus validate(final IProject project, final String path) {
208 return Status.OK_STATUS;
209 }
210
211 // ------------------------------------------------------------------------
212 // Accessors
213 // ------------------------------------------------------------------------
214
215 /**
216 * Get the traces contained in this experiment.
217 *
218 * @return The array of contained traces
219 */
220 public ITmfTrace[] getTraces() {
221 return fTraces;
222 }
223
224 /**
225 * Returns the timestamp of the event at the requested index. If none,
226 * returns null.
227 *
228 * @param index
229 * the event index (rank)
230 * @return the corresponding event timestamp
231 * @since 2.0
232 */
233 public ITmfTimestamp getTimestamp(final int index) {
234 final ITmfContext context = seekEvent(index);
235 final ITmfEvent event = getNext(context);
236 context.dispose();
237 return (event != null) ? event.getTimestamp() : null;
238 }
239
240 /**
241 * Set the file to be used for bookmarks on this experiment
242 *
243 * @param file
244 * the bookmarks file
245 */
246 public void setBookmarksFile(final IFile file) {
247 fBookmarksFile = file;
248 }
249
250 /**
251 * Get the file used for bookmarks on this experiment
252 *
253 * @return the bookmarks file or null if none is set
254 */
255 public IFile getBookmarksFile() {
256 return fBookmarksFile;
257 }
258
259 // ------------------------------------------------------------------------
260 // Request management
261 // ------------------------------------------------------------------------
262
263 /**
264 * @since 2.0
265 */
266 @Override
267 public synchronized ITmfContext armRequest(final ITmfDataRequest request) {
268
269 // Make sure we have something to read from
270 if (fTraces == null) {
271 return null;
272 }
273
274 if (request instanceof ITmfEventRequest
275 && !TmfTimestamp.BIG_BANG.equals(((ITmfEventRequest) request).getRange().getStartTime())
276 && request.getIndex() == 0)
277 {
278 final ITmfContext context = seekEvent(((ITmfEventRequest) request).getRange().getStartTime());
279 ((ITmfEventRequest) request).setStartIndex((int) context.getRank());
280 return context;
281
282 }
283
284 return seekEvent(request.getIndex());
285 }
286
287 // ------------------------------------------------------------------------
288 // ITmfTrace trace positioning
289 // ------------------------------------------------------------------------
290
291 /**
292 * @since 3.0
293 */
294 @Override
295 public synchronized ITmfContext seekEvent(final ITmfLocation location) {
296 // Validate the location
297 if (location != null && !(location instanceof TmfExperimentLocation)) {
298 return null; // Throw an exception?
299 }
300 // Make sure we have something to read from
301 if (fTraces == null) {
302 return null;
303 }
304
305 // Initialize the location array if necessary
306 TmfLocationArray locationArray = ((location == null) ?
307 new TmfLocationArray(fTraces.length) :
308 ((TmfExperimentLocation) location).getLocationInfo());
309
310 ITmfLocation[] locations = locationArray.getLocations();
311 long[] ranks = locationArray.getRanks();
312
313 // Create and populate the context's traces contexts
314 final TmfExperimentContext context = new TmfExperimentContext(fTraces.length);
315
316 // Position the traces
317 long rank = 0;
318 for (int i = 0; i < fTraces.length; i++) {
319 // Get the relevant trace attributes
320 final ITmfContext traceContext = fTraces[i].seekEvent(locations[i]);
321 context.getContexts()[i] = traceContext;
322 traceContext.setRank(ranks[i]);
323 locations[i] = traceContext.getLocation(); // update location after seek
324 context.getEvents()[i] = fTraces[i].getNext(traceContext);
325 rank += ranks[i];
326 }
327
328 // Finalize context
329 context.setLocation(new TmfExperimentLocation(new TmfLocationArray(locations, ranks)));
330 context.setLastTrace(TmfExperimentContext.NO_TRACE);
331 context.setRank(rank);
332
333 return context;
334 }
335
336 // ------------------------------------------------------------------------
337 // ITmfTrace - SeekEvent operations (returning a trace context)
338 // ------------------------------------------------------------------------
339
340 @Override
341 public ITmfContext seekEvent(final double ratio) {
342 final ITmfContext context = seekEvent(Math.round(ratio * getNbEvents()));
343 return context;
344 }
345
346 /**
347 * @since 3.0
348 */
349 @Override
350 public double getLocationRatio(final ITmfLocation location) {
351 if (location instanceof TmfExperimentLocation) {
352 long rank = 0;
353 TmfLocationArray locationArray = ((TmfExperimentLocation) location).getLocationInfo();
354 for (int i = 0; i < locationArray.size(); i++) {
355 rank += locationArray.getRank(i);
356 }
357 return (double) rank / getNbEvents();
358 }
359 return 0.0;
360 }
361
362 /**
363 * @since 3.0
364 */
365 @Override
366 public ITmfLocation getCurrentLocation() {
367 // never used
368 return null;
369 }
370
371 // ------------------------------------------------------------------------
372 // ITmfTrace trace positioning
373 // ------------------------------------------------------------------------
374
375 @Override
376 public synchronized ITmfEvent parseEvent(final ITmfContext context) {
377 final ITmfContext tmpContext = seekEvent(context.getLocation());
378 final ITmfEvent event = getNext(tmpContext);
379 return event;
380 }
381
382 @Override
383 public synchronized ITmfEvent getNext(ITmfContext context) {
384
385 // Validate the context
386 if (!(context instanceof TmfExperimentContext)) {
387 return null; // Throw an exception?
388 }
389
390 // Make sure that we have something to read from
391 if (fTraces == null) {
392 return null;
393 }
394
395 TmfExperimentContext expContext = (TmfExperimentContext) context;
396
397 // If an event was consumed previously, first get the next one from that
398 // trace
399 final int lastTrace = expContext.getLastTrace();
400 if (lastTrace != TmfExperimentContext.NO_TRACE) {
401 final ITmfContext traceContext = expContext.getContexts()[lastTrace];
402 expContext.getEvents()[lastTrace] = fTraces[lastTrace].getNext(traceContext);
403 expContext.setLastTrace(TmfExperimentContext.NO_TRACE);
404 }
405
406 // Scan the candidate events and identify the "next" trace to read from
407 int trace = TmfExperimentContext.NO_TRACE;
408 ITmfTimestamp timestamp = TmfTimestamp.BIG_CRUNCH;
409 for (int i = 0; i < fTraces.length; i++) {
410 final ITmfEvent event = expContext.getEvents()[i];
411 if (event != null && event.getTimestamp() != null) {
412 final ITmfTimestamp otherTS = event.getTimestamp();
413 if (otherTS.compareTo(timestamp, true) < 0) {
414 trace = i;
415 timestamp = otherTS;
416 }
417 }
418 }
419
420 ITmfEvent event = null;
421 if (trace != TmfExperimentContext.NO_TRACE) {
422 event = expContext.getEvents()[trace];
423 if (event != null) {
424 updateAttributes(expContext, event.getTimestamp());
425 expContext.increaseRank();
426 expContext.setLastTrace(trace);
427 final ITmfContext traceContext = expContext.getContexts()[trace];
428
429 // Update the experiment location
430 TmfLocationArray locationArray = new TmfLocationArray(
431 ((TmfExperimentLocation) expContext.getLocation()).getLocationInfo(),
432 trace, traceContext.getLocation(), traceContext.getRank());
433 expContext.setLocation(new TmfExperimentLocation(locationArray));
434
435 processEvent(event);
436 }
437 }
438
439 return event;
440 }
441
442 /**
443 * @since 2.0
444 */
445 @Override
446 public ITmfTimestamp getInitialRangeOffset() {
447 if ((fTraces == null) || (fTraces.length == 0)) {
448 return super.getInitialRangeOffset();
449 }
450
451 ITmfTimestamp initTs = TmfTimestamp.BIG_CRUNCH;
452 for (int i = 0; i < fTraces.length; i++) {
453 ITmfTimestamp ts = fTraces[i].getInitialRangeOffset();
454 if (ts.compareTo(initTs) < 0) {
455 initTs = ts;
456 }
457 }
458 return initTs;
459 }
460
461 /**
462 * Synchronizes the traces of an experiment. By default it only tries to
463 * read a synchronization file if it exists
464 *
465 * @return The synchronization object
466 * @throws TmfTraceException
467 * propagate TmfTraceExceptions
468 * @since 3.0
469 */
470 public synchronized SynchronizationAlgorithm synchronizeTraces() throws TmfTraceException {
471 return synchronizeTraces(false);
472 }
473
474 /**
475 * Synchronizes the traces of an experiment.
476 *
477 * @param doSync
478 * Whether to actually synchronize or just try opening a sync
479 * file
480 * @return The synchronization object
481 * @throws TmfTraceException
482 * propagate TmfTraceExceptions
483 * @since 3.0
484 */
485 public synchronized SynchronizationAlgorithm synchronizeTraces(boolean doSync) throws TmfTraceException {
486
487 /* Set up the path to the synchronization file we'll use */
488 IResource resource = this.getResource();
489 String supplDirectory = null;
490
491 try {
492 /* get the directory where the file will be stored. */
493 if (resource != null) {
494 supplDirectory = resource.getPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER);
495 }
496 } catch (CoreException e) {
497 throw new TmfTraceException(e.toString(), e);
498 }
499
500 final File syncFile = (supplDirectory != null) ? new File(supplDirectory + File.separator + SYNCHRONIZATION_FILE_NAME) : null;
501
502 final SynchronizationAlgorithm syncAlgo = SynchronizationManager.synchronizeTraces(syncFile, fTraces, doSync);
503
504 final TmfTraceSynchronizedSignal signal = new TmfTraceSynchronizedSignal(this, syncAlgo);
505
506 /* Broadcast in separate thread to prevent deadlock */
507 new Thread() {
508 @Override
509 public void run() {
510 broadcast(signal);
511 }
512 }.start();
513
514 return syncAlgo;
515 }
516
517 @Override
518 @SuppressWarnings("nls")
519 public synchronized String toString() {
520 return "[TmfExperiment (" + getName() + ")]";
521 }
522
523 // ------------------------------------------------------------------------
524 // Streaming support
525 // ------------------------------------------------------------------------
526
527 private synchronized void initializeStreamingMonitor() {
528
529 if (fInitialized) {
530 return;
531 }
532 fInitialized = true;
533
534 if (getStreamingInterval() == 0) {
535 final ITmfContext context = seekEvent(0);
536 final ITmfEvent event = getNext(context);
537 context.dispose();
538 if (event == null) {
539 return;
540 }
541 final TmfTimeRange timeRange = new TmfTimeRange(event.getTimestamp(), TmfTimestamp.BIG_CRUNCH);
542 final TmfTraceRangeUpdatedSignal signal = new TmfTraceRangeUpdatedSignal(this, this, timeRange);
543
544 // Broadcast in separate thread to prevent deadlock
545 new Thread() {
546 @Override
547 public void run() {
548 broadcast(signal);
549 }
550 }.start();
551 return;
552 }
553
554 final Thread thread = new Thread("Streaming Monitor for experiment " + getName()) { //$NON-NLS-1$
555 private ITmfTimestamp safeTimestamp = null;
556 private ITmfTimestamp lastSafeTimestamp = null;
557 private TmfTimeRange timeRange = null;
558
559 @Override
560 public void run() {
561 while (!executorIsShutdown()) {
562 if (!getIndexer().isIndexing()) {
563 ITmfTimestamp startTimestamp = TmfTimestamp.BIG_CRUNCH;
564 ITmfTimestamp endTimestamp = TmfTimestamp.BIG_BANG;
565 for (final ITmfTrace trace : fTraces) {
566 if (trace.getStartTime().compareTo(startTimestamp) < 0) {
567 startTimestamp = trace.getStartTime();
568 }
569 if (trace.getStreamingInterval() != 0 && trace.getEndTime().compareTo(endTimestamp) > 0) {
570 endTimestamp = trace.getEndTime();
571 }
572 }
573 if (safeTimestamp != null && (lastSafeTimestamp == null || safeTimestamp.compareTo(lastSafeTimestamp, false) > 0)) {
574 timeRange = new TmfTimeRange(startTimestamp, safeTimestamp);
575 lastSafeTimestamp = safeTimestamp;
576 } else {
577 timeRange = null;
578 }
579 safeTimestamp = endTimestamp;
580 if (timeRange != null) {
581 final TmfTraceRangeUpdatedSignal signal =
582 new TmfTraceRangeUpdatedSignal(TmfExperiment.this, TmfExperiment.this, timeRange);
583 broadcast(signal);
584 }
585 }
586 try {
587 Thread.sleep(getStreamingInterval());
588 } catch (final InterruptedException e) {
589 e.printStackTrace();
590 }
591 }
592 }
593 };
594 thread.start();
595 }
596
597 @Override
598 public long getStreamingInterval() {
599 long interval = 0;
600 for (final ITmfTrace trace : fTraces) {
601 interval = Math.max(interval, trace.getStreamingInterval());
602 }
603 return interval;
604 }
605
606 // ------------------------------------------------------------------------
607 // Signal handlers
608 // ------------------------------------------------------------------------
609
610 @Override
611 @TmfSignalHandler
612 public void traceOpened(TmfTraceOpenedSignal signal) {
613 if (signal.getTrace() == this) {
614 initializeStreamingMonitor();
615 }
616 }
617
618}
This page took 0.047444 seconds and 5 git commands to generate.