1 /*******************************************************************************
2 * Copyright (c) 2009, 2010 Ericsson
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
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.core
.experiment
;
15 import java
.util
.Collections
;
16 import java
.util
.Vector
;
18 import org
.eclipse
.core
.resources
.IFile
;
19 import org
.eclipse
.core
.resources
.IProject
;
20 import org
.eclipse
.core
.resources
.IResource
;
21 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
22 import org
.eclipse
.core
.runtime
.IStatus
;
23 import org
.eclipse
.core
.runtime
.Status
;
24 import org
.eclipse
.core
.runtime
.jobs
.Job
;
25 import org
.eclipse
.linuxtools
.tmf
.core
.component
.TmfEventProvider
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfTimestamp
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimestamp
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.request
.ITmfDataRequest
;
31 import org
.eclipse
.linuxtools
.tmf
.core
.request
.ITmfEventRequest
;
32 import org
.eclipse
.linuxtools
.tmf
.core
.request
.TmfDataRequest
;
33 import org
.eclipse
.linuxtools
.tmf
.core
.request
.TmfEventRequest
;
34 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfEndSynchSignal
;
35 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfExperimentDisposedSignal
;
36 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfExperimentRangeUpdatedSignal
;
37 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfExperimentSelectedSignal
;
38 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfExperimentUpdatedSignal
;
39 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
40 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceUpdatedSignal
;
41 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfContext
;
42 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfLocation
;
43 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
44 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfCheckpoint
;
45 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfContext
;
48 * <b><u>TmfExperiment</u></b>
50 * TmfExperiment presents a time-ordered, unified view of a set of TmfTraces
51 * that are part of a tracing experiment.
54 public class TmfExperiment
<T
extends ITmfEvent
> extends TmfEventProvider
<T
> implements ITmfTrace
<T
> {
56 // ------------------------------------------------------------------------
58 // ------------------------------------------------------------------------
60 // The currently selected experiment
61 protected static TmfExperiment
<?
> fCurrentExperiment
= null;
63 // The set of traces that constitute the experiment
64 protected ITmfTrace
<T
>[] fTraces
;
66 // The total number of events
67 protected long fNbEvents
;
69 // The experiment time range
70 protected TmfTimeRange fTimeRange
;
72 // The experiment reference timestamp (default: ZERO)
73 protected ITmfTimestamp fEpoch
;
75 // The experiment index
76 protected Vector
<TmfCheckpoint
> fCheckpoints
= new Vector
<TmfCheckpoint
>();
78 // The current experiment context
79 protected TmfExperimentContext fExperimentContext
;
81 // Flag to initialize only once
82 private boolean fInitialized
= false;
84 // The experiment bookmarks file
85 private IFile fBookmarksFile
;
87 // The properties resource
88 private IResource fResource
;
90 // ------------------------------------------------------------------------
92 // ------------------------------------------------------------------------
95 public TmfExperiment
<T
> clone() throws CloneNotSupportedException
{
96 throw new CloneNotSupportedException();
100 public boolean validate(final IProject project
, final String path
) {
105 public void initTrace(final String name
, final String path
, final Class
<T
> eventType
) {
113 * @param indexPageSize
115 public TmfExperiment(final Class
<T
> type
, final String id
, final ITmfTrace
<T
>[] traces
, final ITmfTimestamp epoch
,
116 final int indexPageSize
) {
117 this(type
, id
, traces
, TmfTimestamp
.ZERO
, indexPageSize
, false);
120 public TmfExperiment(final Class
<T
> type
, final String id
, final ITmfTrace
<T
>[] traces
, final ITmfTimestamp epoch
,
121 final int indexPageSize
, final boolean preIndexExperiment
) {
126 fIndexPageSize
= indexPageSize
;
127 fTimeRange
= TmfTimeRange
.NULL_RANGE
;
129 if (preIndexExperiment
) {
130 indexExperiment(true, 0, TmfTimeRange
.ETERNITY
);
135 protected TmfExperiment(final String id
, final Class
<T
> type
) {
144 public TmfExperiment(final Class
<T
> type
, final String id
, final ITmfTrace
<T
>[] traces
) {
145 this(type
, id
, traces
, TmfTimestamp
.ZERO
, DEFAULT_INDEX_PAGE_SIZE
);
152 * @param indexPageSize
154 public TmfExperiment(final Class
<T
> type
, final String id
, final ITmfTrace
<T
>[] traces
, final int indexPageSize
) {
155 this(type
, id
, traces
, TmfTimestamp
.ZERO
, indexPageSize
);
159 * Clears the experiment
162 @SuppressWarnings("rawtypes")
163 public synchronized void dispose() {
165 final TmfExperimentDisposedSignal
<T
> signal
= new TmfExperimentDisposedSignal
<T
>(this, this);
167 if (fCurrentExperiment
== this)
168 fCurrentExperiment
= null;
170 if (fTraces
!= null) {
171 for (final ITmfTrace trace
: fTraces
)
175 if (fCheckpoints
!= null)
176 fCheckpoints
.clear();
180 // ------------------------------------------------------------------------
182 // ------------------------------------------------------------------------
185 public long getNbEvents() {
190 public int getIndexPageSize() {
191 return fIndexPageSize
;
195 public TmfTimeRange
getTimeRange() {
200 public ITmfTimestamp
getStartTime() {
201 return fTimeRange
.getStartTime();
205 public ITmfTimestamp
getEndTime() {
206 return fTimeRange
.getEndTime();
209 public Vector
<TmfCheckpoint
> getCheckpoints() {
213 // ------------------------------------------------------------------------
215 // ------------------------------------------------------------------------
217 public static void setCurrentExperiment(final TmfExperiment
<?
> experiment
) {
218 if (fCurrentExperiment
!= null && fCurrentExperiment
!= experiment
)
219 fCurrentExperiment
.dispose();
220 fCurrentExperiment
= experiment
;
223 public static TmfExperiment
<?
> getCurrentExperiment() {
224 return fCurrentExperiment
;
227 public ITmfTimestamp
getEpoch() {
231 public ITmfTrace
<T
>[] getTraces() {
236 * Returns the rank of the first event with the requested timestamp. If
237 * none, returns the index of the next event (if any).
239 * @param timestamp the event timestamp
240 * @return the corresponding event rank
243 public long getRank(final ITmfTimestamp timestamp
) {
244 final TmfExperimentContext context
= seekEvent(timestamp
);
245 return context
.getRank();
249 * Returns the timestamp of the event at the requested index. If none,
252 * @param index the event index (rank)
253 * @return the corresponding event timestamp
255 public ITmfTimestamp
getTimestamp(final int index
) {
256 final TmfExperimentContext context
= seekEvent(index
);
257 final ITmfEvent event
= getNextEvent(context
);
258 return (event
!= null) ? event
.getTimestamp() : null;
261 // ------------------------------------------------------------------------
263 // ------------------------------------------------------------------------
266 * Update the global time range
268 protected void updateTimeRange() {
269 ITmfTimestamp startTime
= fTimeRange
!= TmfTimeRange
.NULL_RANGE ? fTimeRange
.getStartTime()
270 : TmfTimestamp
.BIG_CRUNCH
;
271 ITmfTimestamp endTime
= fTimeRange
!= TmfTimeRange
.NULL_RANGE ? fTimeRange
.getEndTime() : TmfTimestamp
.BIG_BANG
;
273 for (final ITmfTrace
<T
> trace
: fTraces
) {
274 final ITmfTimestamp traceStartTime
= trace
.getStartTime();
275 if (traceStartTime
.compareTo(startTime
, true) < 0)
276 startTime
= traceStartTime
;
277 final ITmfTimestamp traceEndTime
= trace
.getEndTime();
278 if (traceEndTime
.compareTo(endTime
, true) > 0)
279 endTime
= traceEndTime
;
281 fTimeRange
= new TmfTimeRange(startTime
, endTime
);
284 // ------------------------------------------------------------------------
286 // ------------------------------------------------------------------------
288 public ITmfContext
armRequest(final ITmfDataRequest
<T
> request
) {
289 // Tracer.trace("Ctx: Arming request - start");
290 ITmfTimestamp timestamp
= (request
instanceof ITmfEventRequest
<?
>) ?
((ITmfEventRequest
<T
>) request
).getRange().getStartTime() : null;
291 if (TmfTimestamp
.BIG_BANG
.equals(timestamp
) || request
.getIndex() > 0)
292 timestamp
= null; // use request index
293 TmfExperimentContext context
= null;
294 if (timestamp
!= null) {
296 context
= seekEvent(timestamp
);
297 ((ITmfEventRequest
<T
>) request
).setStartIndex((int) context
.getRank());
298 } else // Seek by rank
299 if ((fExperimentContext
!= null) && fExperimentContext
.getRank() == request
.getIndex())
300 // We are already at the right context -> no need to seek
301 context
= fExperimentContext
;
303 context
= seekEvent(request
.getIndex());
304 // Tracer.trace("Ctx: Arming request - done");
308 @SuppressWarnings("unchecked")
310 public T
getNext(final ITmfContext context
) {
311 if (context
instanceof TmfExperimentContext
)
312 return (T
) getNextEvent(context
);
316 // ------------------------------------------------------------------------
317 // ITmfTrace trace positioning
318 // ------------------------------------------------------------------------
320 // Returns a brand new context based on the location provided
321 // and initializes the event queues
323 public synchronized TmfExperimentContext
seekLocation(final ITmfLocation
<?
> location
) {
324 // Validate the location
325 if (location
!= null && !(location
instanceof TmfExperimentLocation
))
326 return null; // Throw an exception?
331 // Instantiate the location
332 final TmfExperimentLocation expLocation
= (location
== null) ?
new TmfExperimentLocation(new TmfLocationArray(
333 new ITmfLocation
<?
>[fTraces
.length
]), new long[fTraces
.length
]) : (TmfExperimentLocation
) location
.clone();
335 // Create and populate the context's traces contexts
336 final TmfExperimentContext context
= new TmfExperimentContext(fTraces
, new ITmfContext
[fTraces
.length
]);
337 // Tracer.trace("Ctx: SeekLocation - start");
340 for (int i
= 0; i
< fTraces
.length
; i
++) {
341 // Get the relevant trace attributes
342 final ITmfLocation
<?
> traceLocation
= expLocation
.getLocation().locations
[i
];
343 final long traceRank
= expLocation
.getRanks()[i
];
345 // Set the corresponding sub-context
346 context
.getContexts()[i
] = fTraces
[i
].seekLocation(traceLocation
);
347 context
.getContexts()[i
].setRank(traceRank
);
350 // Set the trace location and read the corresponding event
352 * The (TmfContext) cast should be safe since we created 'context'
353 * ourselves higher up.
355 expLocation
.getLocation().locations
[i
] = context
.getContexts()[i
].getLocation().clone();
356 context
.getEvents()[i
] = fTraces
[i
].getNextEvent(context
.getContexts()[i
]);
359 // Tracer.trace("Ctx: SeekLocation - done");
362 context
.setLocation(expLocation
);
363 context
.setLastTrace(TmfExperimentContext
.NO_TRACE
);
364 context
.setRank(rank
);
366 fExperimentContext
= context
;
373 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools .tmf.event.TmfTimestamp)
376 public synchronized TmfExperimentContext
seekEvent(ITmfTimestamp timestamp
) {
378 // Tracer.trace("Ctx: seekEvent(TS) - start");
380 if (timestamp
== null)
381 timestamp
= TmfTimestamp
.BIG_BANG
;
383 // First, find the right checkpoint
384 int index
= Collections
.binarySearch(fCheckpoints
, new TmfCheckpoint(timestamp
, null));
386 // In the very likely case that the checkpoint was not found, bsearch
387 // returns its negated would-be location (not an offset...). From that
388 // index, we can then position the stream and get the event.
390 index
= Math
.max(0, -(index
+ 2));
392 // Position the experiment at the checkpoint
393 ITmfLocation
<?
> location
;
394 synchronized (fCheckpoints
) {
395 if (fCheckpoints
.size() > 0) {
396 if (index
>= fCheckpoints
.size())
397 index
= fCheckpoints
.size() - 1;
398 location
= fCheckpoints
.elementAt(index
).getLocation();
403 final TmfExperimentContext context
= seekLocation(location
);
404 context
.setRank((long) index
* fIndexPageSize
);
406 // And locate the event
407 ITmfEvent event
= parseEvent(context
);
408 while ((event
!= null) && (event
.getTimestamp().compareTo(timestamp
, false) < 0)) {
409 getNextEvent(context
);
410 event
= parseEvent(context
);
414 context
.setLocation(null);
415 context
.setRank(ITmfContext
.UNKNOWN_RANK
);
424 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(long)
427 public synchronized TmfExperimentContext
seekEvent(final long rank
) {
429 // Tracer.trace("Ctx: seekEvent(rank) - start");
431 // Position the stream at the previous checkpoint
432 int index
= (int) rank
/ fIndexPageSize
;
433 ITmfLocation
<?
> location
;
434 synchronized (fCheckpoints
) {
435 if (fCheckpoints
.size() == 0)
438 if (index
>= fCheckpoints
.size())
439 index
= fCheckpoints
.size() - 1;
440 location
= fCheckpoints
.elementAt(index
).getLocation();
444 final TmfExperimentContext context
= seekLocation(location
);
445 context
.setRank((long) index
* fIndexPageSize
);
447 // And locate the event
448 ITmfEvent event
= parseEvent(context
);
449 long pos
= context
.getRank();
450 while ((event
!= null) && (pos
++ < rank
)) {
451 getNextEvent(context
);
452 event
= parseEvent(context
);
456 context
.setLocation(null);
457 context
.setRank(ITmfContext
.UNKNOWN_RANK
);
464 public TmfContext
seekLocation(final double ratio
) {
465 final TmfContext context
= seekEvent((long) (ratio
* getNbEvents()));
470 public double getLocationRatio(final ITmfLocation
<?
> location
) {
471 if (location
instanceof TmfExperimentLocation
)
472 return (double) seekLocation(location
).getRank() / getNbEvents();
477 public ITmfLocation
<?
> getCurrentLocation() {
478 if (fExperimentContext
!= null)
479 return fExperimentContext
.getLocation();
483 // private void dumpContext(TmfExperimentContext context, boolean isBefore) {
485 // TmfContext context0 = context.getContexts()[0];
486 // TmfEvent event0 = context.getEvents()[0];
487 // TmfExperimentLocation location0 = (TmfExperimentLocation) context.getLocation();
488 // long rank0 = context.getRank();
489 // int trace = context.getLastTrace();
491 // StringBuffer result = new StringBuffer("Ctx: " + (isBefore ? "B " : "A "));
493 // result.append("[Ctx: fLoc= " + context0.getLocation().toString() + ", fRnk= " + context0.getRank() + "] ");
494 // result.append("[Evt: " + event0.getTimestamp().toString() + "] ");
495 // result.append("[Loc: fLoc= " + location0.getLocation()[0].toString() + ", fRnk= " + location0.getRanks()[0] + "] ");
496 // result.append("[Rnk: " + rank0 + "], [Trc: " + trace + "]");
497 // Tracer.trace(result.toString());
501 * Scan the next events from all traces and return the next one in
502 * chronological order.
504 * @param context the trace context
505 * @return the next event
508 public synchronized ITmfEvent
getNextEvent(final ITmfContext context
) {
510 // Validate the context
511 if (!(context
instanceof TmfExperimentContext
))
512 return null; // Throw an exception?
514 if (!context
.equals(fExperimentContext
))
515 // Tracer.trace("Ctx: Restoring context");
516 fExperimentContext
= seekLocation(context
.getLocation());
518 final TmfExperimentContext expContext
= (TmfExperimentContext
) context
;
520 // dumpContext(expContext, true);
522 // If an event was consumed previously, get the next one from that trace
523 final int lastTrace
= expContext
.getLastTrace();
524 if (lastTrace
!= TmfExperimentContext
.NO_TRACE
) {
525 final ITmfContext traceContext
= expContext
.getContexts()[lastTrace
];
526 expContext
.getEvents()[lastTrace
] = expContext
.getTraces()[lastTrace
].getNextEvent(traceContext
);
527 expContext
.setLastTrace(TmfExperimentContext
.NO_TRACE
);
530 // Scan the candidate events and identify the "next" trace to read from
531 final ITmfEvent eventArray
[] = expContext
.getEvents();
532 if (eventArray
== null)
534 int trace
= TmfExperimentContext
.NO_TRACE
;
535 ITmfTimestamp timestamp
= TmfTimestamp
.BIG_CRUNCH
;
536 if (eventArray
.length
== 1) {
537 if (eventArray
[0] != null) {
538 timestamp
= eventArray
[0].getTimestamp();
542 for (int i
= 0; i
< eventArray
.length
; i
++) {
543 final ITmfEvent event
= eventArray
[i
];
544 if (event
!= null && event
.getTimestamp() != null) {
545 final ITmfTimestamp otherTS
= event
.getTimestamp();
546 if (otherTS
.compareTo(timestamp
, true) < 0) {
552 // Update the experiment context and set the "next" event
553 ITmfEvent event
= null;
554 if (trace
!= TmfExperimentContext
.NO_TRACE
) {
555 updateIndex(expContext
, timestamp
);
557 final ITmfContext traceContext
= expContext
.getContexts()[trace
];
558 final TmfExperimentLocation expLocation
= (TmfExperimentLocation
) expContext
.getLocation();
559 // expLocation.getLocation()[trace] = traceContext.getLocation().clone();
560 expLocation
.getLocation().locations
[trace
] = traceContext
.getLocation().clone();
562 // updateIndex(expContext, timestamp);
564 expLocation
.getRanks()[trace
] = traceContext
.getRank();
565 expContext
.setLastTrace(trace
);
566 expContext
.increaseRank();
567 event
= expContext
.getEvents()[trace
];
568 fExperimentContext
= expContext
;
571 // if (event != null) {
572 // Tracer.trace("Exp: " + (expContext.getRank() - 1) + ": " + event.getTimestamp().toString());
573 // dumpContext(expContext, false);
574 // Tracer.trace("Ctx: Event returned= " + event.getTimestamp().toString());
580 public synchronized void updateIndex(final ITmfContext context
, final ITmfTimestamp timestamp
) {
581 // Build the index as we go along
582 final long rank
= context
.getRank();
583 if (context
.hasValidRank() && (rank
% fIndexPageSize
) == 0) {
584 // Determine the table position
585 final long position
= rank
/ fIndexPageSize
;
586 // Add new entry at proper location (if empty)
587 if (fCheckpoints
.size() == position
) {
588 final ITmfLocation
<?
> location
= context
.getLocation().clone();
589 fCheckpoints
.add(new TmfCheckpoint(timestamp
.clone(), location
));
590 // System.out.println(this + "[" + (fCheckpoints.size() - 1) + "] " + timestamp + ", "
591 // + location.toString());
597 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#parseEvent(org.eclipse.linuxtools .tmf.trace.TmfContext)
600 public ITmfEvent
parseEvent(final ITmfContext context
) {
602 // Validate the context
603 if (!(context
instanceof TmfExperimentContext
))
604 return null; // Throw an exception?
606 if (!context
.equals(fExperimentContext
))
607 // Tracer.trace("Ctx: Restoring context");
608 seekLocation(context
.getLocation());
610 final TmfExperimentContext expContext
= (TmfExperimentContext
) context
;
612 // If an event was consumed previously, get the next one from that trace
613 final int lastTrace
= expContext
.getLastTrace();
614 if (lastTrace
!= TmfExperimentContext
.NO_TRACE
) {
615 final ITmfContext traceContext
= expContext
.getContexts()[lastTrace
];
616 expContext
.getEvents()[lastTrace
] = expContext
.getTraces()[lastTrace
].getNextEvent(traceContext
);
617 expContext
.setLastTrace(TmfExperimentContext
.NO_TRACE
);
618 fExperimentContext
= (TmfExperimentContext
) context
;
621 // Scan the candidate events and identify the "next" trace to read from
622 int trace
= TmfExperimentContext
.NO_TRACE
;
623 ITmfTimestamp timestamp
= TmfTimestamp
.BIG_CRUNCH
;
624 for (int i
= 0; i
< expContext
.getTraces().length
; i
++) {
625 final ITmfEvent event
= expContext
.getEvents()[i
];
626 if (event
!= null && event
.getTimestamp() != null) {
627 final ITmfTimestamp otherTS
= event
.getTimestamp();
628 if (otherTS
.compareTo(timestamp
, true) < 0) {
635 ITmfEvent event
= null;
636 if (trace
!= TmfExperimentContext
.NO_TRACE
)
637 event
= expContext
.getEvents()[trace
];
645 * @see java.lang.Object#toString()
648 @SuppressWarnings("nls")
649 public String
toString() {
650 return "[TmfExperiment (" + getName() + ")]";
653 // ------------------------------------------------------------------------
655 // ------------------------------------------------------------------------
657 private synchronized void initializeStreamingMonitor() {
662 if (getStreamingInterval() == 0) {
663 final TmfContext context
= seekLocation(null);
664 final ITmfEvent event
= getNext(context
);
667 final TmfTimeRange timeRange
= new TmfTimeRange(event
.getTimestamp().clone(), TmfTimestamp
.BIG_CRUNCH
);
668 final TmfExperimentRangeUpdatedSignal signal
= new TmfExperimentRangeUpdatedSignal(this, this, timeRange
);
670 // Broadcast in separate thread to prevent deadlock
681 final Thread thread
= new Thread("Streaming Monitor for experiment " + getName()) { //$NON-NLS-1$
683 ITmfTimestamp safeTimestamp
= null;
684 TmfTimeRange timeRange
= null;
688 while (!fExecutor
.isShutdown()) {
689 if (!isIndexingBusy()) {
690 ITmfTimestamp startTimestamp
= TmfTimestamp
.BIG_CRUNCH
;
691 ITmfTimestamp endTimestamp
= TmfTimestamp
.BIG_BANG
;
692 for (final ITmfTrace
<T
> trace
: fTraces
) {
693 if (trace
.getStartTime().compareTo(startTimestamp
) < 0)
694 startTimestamp
= trace
.getStartTime();
695 if (trace
.getStreamingInterval() != 0 && trace
.getEndTime().compareTo(endTimestamp
) > 0)
696 endTimestamp
= trace
.getEndTime();
698 if (safeTimestamp
!= null && safeTimestamp
.compareTo(getTimeRange().getEndTime(), false) > 0)
699 timeRange
= new TmfTimeRange(startTimestamp
, safeTimestamp
);
702 safeTimestamp
= endTimestamp
;
703 if (timeRange
!= null) {
704 final TmfExperimentRangeUpdatedSignal signal
=
705 new TmfExperimentRangeUpdatedSignal(TmfExperiment
.this, TmfExperiment
.this,
711 Thread
.sleep(getStreamingInterval());
712 } catch (final InterruptedException e
) {
724 * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStreamingInterval()
727 public long getStreamingInterval() {
729 for (final ITmfTrace
<T
> trace
: fTraces
)
730 interval
= Math
.max(interval
, trace
.getStreamingInterval());
735 * The experiment holds the globally ordered events of its set of traces. It
736 * is expected to provide access to each individual event by index i.e. it
737 * must be possible to request the Nth event of the experiment.
739 * The purpose of the index is to keep the information needed to rapidly
740 * restore the traces contexts at regular intervals (every INDEX_PAGE_SIZE
744 // The index page size
745 private static final int DEFAULT_INDEX_PAGE_SIZE
= 5000;
746 protected int fIndexPageSize
;
747 protected boolean fIndexing
= false;
748 protected TmfTimeRange fIndexingPendingRange
= TmfTimeRange
.NULL_RANGE
;
750 private Integer fEndSynchReference
;
752 // private static BufferedWriter fEventLog = null;
753 // private static BufferedWriter openLogFile(String filename) {
754 // BufferedWriter outfile = null;
756 // outfile = new BufferedWriter(new FileWriter(filename));
757 // } catch (IOException e) {
758 // e.printStackTrace();
763 protected boolean isIndexingBusy() {
764 synchronized (fCheckpoints
) {
770 public void indexTrace(final boolean waitForCompletion
) {
771 if (waitForCompletion
)
772 initializeStreamingMonitor();
775 @SuppressWarnings("unchecked")
776 private void indexExperiment(final boolean waitForCompletion
, final int index
, final TmfTimeRange timeRange
) {
778 synchronized (fCheckpoints
) {
784 final Job job
= new Job("Indexing " + getName() + "...") { //$NON-NLS-1$ //$NON-NLS-2$
787 protected IStatus
run(final IProgressMonitor monitor
) {
788 while (!monitor
.isCanceled())
791 } catch (final InterruptedException e
) {
792 return Status
.OK_STATUS
;
795 return Status
.OK_STATUS
;
800 // fEventLog = openLogFile("TraceEvent.log");
801 // System.out.println(System.currentTimeMillis() + ": Experiment indexing started");
803 final ITmfEventRequest
<ITmfEvent
> request
= new TmfEventRequest
<ITmfEvent
>(ITmfEvent
.class, timeRange
, index
,
804 TmfDataRequest
.ALL_DATA
,
805 fIndexPageSize
, ITmfDataRequest
.ExecutionType
.BACKGROUND
) { // PATA
808 // long indexingStart = System.nanoTime();
810 ITmfTimestamp startTime
= (fTimeRange
== TmfTimeRange
.NULL_RANGE
) ?
null : fTimeRange
.getStartTime();
811 ITmfTimestamp lastTime
= (fTimeRange
== TmfTimeRange
.NULL_RANGE
) ?
null : fTimeRange
.getEndTime();
812 long initialNbEvents
= fNbEvents
;
815 public void handleStarted() {
816 super.handleStarted();
820 public void handleData(final ITmfEvent event
) {
821 super.handleData(event
);
823 final ITmfTimestamp ts
= event
.getTimestamp();
824 if (startTime
== null)
825 startTime
= ts
.clone();
826 lastTime
= ts
.clone();
827 if ((getNbRead() % fIndexPageSize
) == 1 && getNbRead() != 1)
833 public void handleSuccess() {
834 // long indexingEnd = System.nanoTime();
836 // if the end time is a real value then it is the streaming safe
838 // set the last time to the safe time stamp to prevent
839 // unnecessary indexing requests
840 if (getRange().getEndTime() != TmfTimestamp
.BIG_CRUNCH
)
841 lastTime
= getRange().getEndTime();
843 // System.out.println(System.currentTimeMillis() + ": Experiment indexing completed");
845 // long average = (indexingEnd - indexingStart) / fNbEvents;
846 // System.out.println(getName() + ": start=" + startTime + ", end=" + lastTime + ", elapsed="
847 // + (indexingEnd * 1.0 - indexingStart) / 1000000000);
848 // System.out.println(getName() + ": nbEvents=" + fNbEvents + " (" + (average / 1000) + "."
849 // + (average % 1000) + " us/evt)");
850 super.handleSuccess();
854 public void handleCompleted() {
856 super.handleCompleted();
857 synchronized (fCheckpoints
) {
859 if (fIndexingPendingRange
!= TmfTimeRange
.NULL_RANGE
) {
860 indexExperiment(false, (int) fNbEvents
, fIndexingPendingRange
);
861 fIndexingPendingRange
= TmfTimeRange
.NULL_RANGE
;
866 private void updateExperiment() {
867 final int nbRead
= getNbRead();
868 if (startTime
!= null)
869 fTimeRange
= new TmfTimeRange(startTime
, lastTime
.clone());
871 // updateTimeRange();
873 fNbEvents
= initialNbEvents
+ nbRead
;
879 sendRequest((ITmfDataRequest
<T
>) request
);
880 if (waitForCompletion
)
882 request
.waitForCompletion();
883 } catch (final InterruptedException e
) {
888 protected void notifyListeners() {
889 broadcast(new TmfExperimentUpdatedSignal(this, this)); // , null));
890 // broadcast(new TmfExperimentRangeUpdatedSignal(this, this,
891 // fTimeRange)); // , null));
894 // ------------------------------------------------------------------------
896 // ------------------------------------------------------------------------
899 public void experimentSelected(final TmfExperimentSelectedSignal
<T
> signal
) {
900 final TmfExperiment
<?
> experiment
= signal
.getExperiment();
901 if (experiment
== this) {
902 setCurrentExperiment(experiment
);
903 fEndSynchReference
= Integer
.valueOf(signal
.getReference());
908 public void endSync(final TmfEndSynchSignal signal
) {
909 if (fEndSynchReference
!= null && fEndSynchReference
.intValue() == signal
.getReference()) {
910 fEndSynchReference
= null;
911 initializeStreamingMonitor();
916 public void experimentUpdated(final TmfExperimentUpdatedSignal signal
) {
920 public void experimentRangeUpdated(final TmfExperimentRangeUpdatedSignal signal
) {
921 if (signal
.getExperiment() == this)
922 indexExperiment(false, (int) fNbEvents
, signal
.getRange());
926 public void traceUpdated(final TmfTraceUpdatedSignal signal
) {
927 for (final ITmfTrace
<T
> trace
: fTraces
)
928 if (trace
== signal
.getTrace()) {
929 synchronized (fCheckpoints
) {
931 if (fIndexingPendingRange
== TmfTimeRange
.NULL_RANGE
)
932 fIndexingPendingRange
= signal
.getRange();
934 ITmfTimestamp startTime
= fIndexingPendingRange
.getStartTime();
935 ITmfTimestamp endTime
= fIndexingPendingRange
.getEndTime();
936 if (signal
.getRange().getStartTime().compareTo(startTime
) < 0)
937 startTime
= signal
.getRange().getStartTime();
938 if (signal
.getRange().getEndTime().compareTo(endTime
) > 0)
939 endTime
= signal
.getRange().getEndTime();
940 fIndexingPendingRange
= new TmfTimeRange(startTime
, endTime
);
945 indexExperiment(false, (int) fNbEvents
, signal
.getRange());
951 public String
getPath() {
952 // TODO Auto-generated method stub
957 * Set the file to be used for bookmarks on this experiment
959 * @param file the bookmarks file
961 public void setBookmarksFile(final IFile file
) {
962 fBookmarksFile
= file
;
966 * Get the file used for bookmarks on this experiment
968 * @return the bookmarks file or null if none is set
970 public IFile
getBookmarksFile() {
971 return fBookmarksFile
;
978 * org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#setResource(org.eclipse
979 * .core.resources.IResource)
982 public void setResource(final IResource resource
) {
983 fResource
= resource
;
989 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getResource()
992 public IResource
getResource() {