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