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