1 /*******************************************************************************
2 * Copyright (c) 2009, 2015 Ericsson, École Polytechnique de Montréal
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 * 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 * Bernd Hufmann - Updated for added interfaces to ITmfEventProvider
17 *******************************************************************************/
19 package org
.eclipse
.tracecompass
.tmf
.core
.trace
.experiment
;
21 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
24 import java
.math
.BigInteger
;
25 import java
.nio
.ByteBuffer
;
26 import java
.util
.Collection
;
27 import java
.util
.Collections
;
28 import java
.util
.List
;
29 import java
.util
.concurrent
.locks
.Lock
;
30 import java
.util
.concurrent
.locks
.ReentrantLock
;
31 import java
.util
.function
.Function
;
32 import java
.util
.stream
.Collectors
;
34 import org
.eclipse
.core
.resources
.IProject
;
35 import org
.eclipse
.core
.resources
.IResource
;
36 import org
.eclipse
.core
.runtime
.CoreException
;
37 import org
.eclipse
.core
.runtime
.IStatus
;
38 import org
.eclipse
.core
.runtime
.MultiStatus
;
39 import org
.eclipse
.core
.runtime
.Status
;
40 import org
.eclipse
.jdt
.annotation
.NonNull
;
41 import org
.eclipse
.jdt
.annotation
.Nullable
;
42 import org
.eclipse
.tracecompass
.internal
.tmf
.core
.Activator
;
43 import org
.eclipse
.tracecompass
.internal
.tmf
.core
.synchronization
.TmfTimestampTransform
;
44 import org
.eclipse
.tracecompass
.internal
.tmf
.core
.trace
.experiment
.TmfExperimentContext
;
45 import org
.eclipse
.tracecompass
.internal
.tmf
.core
.trace
.experiment
.TmfExperimentLocation
;
46 import org
.eclipse
.tracecompass
.internal
.tmf
.core
.trace
.experiment
.TmfLocationArray
;
47 import org
.eclipse
.tracecompass
.tmf
.core
.TmfCommonConstants
;
48 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
49 import org
.eclipse
.tracecompass
.tmf
.core
.exceptions
.TmfTraceException
;
50 import org
.eclipse
.tracecompass
.tmf
.core
.project
.model
.ITmfPropertiesProvider
;
51 import org
.eclipse
.tracecompass
.tmf
.core
.request
.ITmfEventRequest
;
52 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
53 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
54 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceRangeUpdatedSignal
;
55 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSynchronizedSignal
;
56 import org
.eclipse
.tracecompass
.tmf
.core
.synchronization
.ITmfTimestampTransform
;
57 import org
.eclipse
.tracecompass
.tmf
.core
.synchronization
.SynchronizationAlgorithm
;
58 import org
.eclipse
.tracecompass
.tmf
.core
.synchronization
.SynchronizationManager
;
59 import org
.eclipse
.tracecompass
.tmf
.core
.synchronization
.TimestampTransformFactory
;
60 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
61 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
62 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
63 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
64 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
65 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTrace
;
66 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
67 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.indexer
.ITmfPersistentlyIndexable
;
68 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.indexer
.ITmfTraceIndexer
;
69 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.indexer
.TmfBTreeTraceIndexer
;
70 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.ITmfLocation
;
72 import com
.google
.common
.collect
.HashMultimap
;
73 import com
.google
.common
.collect
.Multimap
;
76 * TmfExperiment presents a time-ordered, unified view of a set of ITmfTrace:s
77 * that are part of a tracing experiment.
80 * @author Francois Chouinard
82 public class TmfExperiment
extends TmfTrace
implements ITmfPersistentlyIndexable
{
84 // ------------------------------------------------------------------------
86 // ------------------------------------------------------------------------
89 * The file name of the Synchronization
91 * @deprecated This file name shouldn't be used directly anymore. All
92 * synchronization files have been moved to a folder and you
93 * should use the {@link #getSynchronizationFolder(boolean)}
94 * method to return the path to this folder.
97 public static final String SYNCHRONIZATION_FILE_NAME
= "synchronization.bin"; //$NON-NLS-1$
100 * The name of the directory containing trace synchronization data. This
101 * directory typically will be preserved when traces are synchronized.
102 * Analysis involved in synchronization can put their supplementary files in
103 * there so they are not deleted when synchronized traces are copied.
105 private static final String SYNCHRONIZATION_DIRECTORY
= "sync_data"; //$NON-NLS-1$
108 * The default index page size
110 public static final int DEFAULT_INDEX_PAGE_SIZE
= 5000;
113 * Property name for traces defining a clock offset.
115 private static final String CLOCK_OFFSET_PROPERTY
= "clock_offset"; //$NON-NLS-1$
118 * If the automatic clock offset is higher than this value, emit a warning.
120 private static final long CLOCK_OFFSET_THRESHOLD_NS
= 500000;
122 // ------------------------------------------------------------------------
124 // ------------------------------------------------------------------------
127 * The set of traces that constitute the experiment
129 private boolean fInitialized
= false;
132 * Lock for synchronization methods. These methods cannot be 'synchronized'
133 * since it makes it impossible to use an event request on the experiment
134 * during synchronization (the request thread would block)
136 private final Lock fSyncLock
= new ReentrantLock();
138 // ------------------------------------------------------------------------
140 // ------------------------------------------------------------------------
143 * Default constructor. Should not be used directly, but is needed for
146 * @deprecated Do not call this directly (but do not remove it either!)
149 public TmfExperiment() {
154 * Constructor of an experiment, taking the type, path, traces,
155 * indexPageSize and resource
160 * The experiment path
162 * The experiment set of traces
163 * @param indexPageSize
164 * The experiment index page size. You can use
165 * {@link TmfExperiment#DEFAULT_INDEX_PAGE_SIZE} for a default
168 * The resource associated to the experiment. You can use 'null'
169 * for no resources (tests, etc.)
171 public TmfExperiment(final Class
<?
extends ITmfEvent
> type
,
173 final ITmfTrace
[] traces
,
174 final int indexPageSize
,
175 final @Nullable IResource resource
) {
176 initExperiment(type
, path
, traces
, indexPageSize
, resource
);
180 protected ITmfTraceIndexer
createIndexer(int interval
) {
181 if (getCheckpointSize() > 0) {
182 return new TmfBTreeTraceIndexer(this, interval
);
184 return super.createIndexer(interval
);
188 * Clears the experiment
191 public synchronized void dispose() {
193 // Clean up the index if applicable
194 if (getIndexer() != null) {
195 getIndexer().dispose();
201 // ------------------------------------------------------------------------
202 // ITmfTrace - Initializers
203 // ------------------------------------------------------------------------
206 public void initTrace(final IResource resource
, final String path
, final Class
<?
extends ITmfEvent
> type
) {
207 /* Do nothing for experiments */
211 * Initialization of an experiment, taking the type, path, traces,
212 * indexPageSize and resource
217 * the experiment path
219 * the experiment set of traces
220 * @param indexPageSize
221 * the experiment index page size
223 * the resource associated to the experiment
225 public void initExperiment(final Class
<?
extends ITmfEvent
> type
,
227 final ITmfTrace
[] traces
,
228 final int indexPageSize
,
229 final @Nullable IResource resource
) {
231 setCacheSize(indexPageSize
);
232 setStreamingInterval(0);
234 Multimap
<String
, ITmfTrace
> tracesPerHost
= HashMultimap
.create();
236 // traces have to be set before super.initialize()
237 if (traces
!= null) {
239 for (ITmfTrace trace
: traces
) {
241 tracesPerHost
.put(trace
.getHostId(), trace
);
248 super.initialize(resource
, path
, type
);
249 } catch (TmfTraceException e
) {
250 Activator
.logError("Error initializing experiment", e
); //$NON-NLS-1$
253 if (resource
!= null) {
258 * For all traces on the same host, if two or more specify different
259 * clock offsets, adjust their clock offset by the average of all of them.
261 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=484620
263 Function
<ITmfPropertiesProvider
, @Nullable Long
> offsetGetter
= trace
-> {
264 String offset
= trace
.getProperties().get(CLOCK_OFFSET_PROPERTY
);
265 if (offset
== null) {
269 return Long
.parseLong(offset
);
270 } catch (NumberFormatException e
) {
275 for (String host
: tracesPerHost
.keySet()) {
277 * Only attempt to synchronize traces that provide a clock_offset
280 Collection
<ITmfPropertiesProvider
> tracesToSynchronize
= tracesPerHost
.get(host
).stream()
281 .filter(trace
-> trace
instanceof ITmfPropertiesProvider
)
282 .map(trace
-> (ITmfPropertiesProvider
) trace
)
283 .filter(trace
-> offsetGetter
.apply(trace
) != null)
284 .collect(Collectors
.toList());
286 if (tracesToSynchronize
.size() < 2) {
290 /* Only synchronize traces if they haven't previously been synchronized */
291 if (tracesToSynchronize
.stream()
292 .map(trace
-> ((ITmfTrace
) trace
).getTimestampTransform())
293 .anyMatch(transform
-> !transform
.equals(TmfTimestampTransform
.IDENTITY
))) {
297 /* Calculate the average of all clock offsets */
298 BigInteger sum
= BigInteger
.ZERO
;
299 for (ITmfPropertiesProvider trace
: tracesToSynchronize
) {
300 long offset
= checkNotNull(offsetGetter
.apply(trace
));
301 sum
= sum
.add(BigInteger
.valueOf(offset
));
303 long average
= sum
.divide(BigInteger
.valueOf(tracesToSynchronize
.size())).longValue();
305 if (average
> CLOCK_OFFSET_THRESHOLD_NS
) {
306 Activator
.logWarning("Average clock correction (" + average
+ ") is higher than threshold of " + //$NON-NLS-1$ //$NON-NLS-2$
307 CLOCK_OFFSET_THRESHOLD_NS
+ " ns for experiment " + this.toString()); //$NON-NLS-1$
311 * Apply the offset correction to all identified traces, but only if
312 * they do not already have an equivalent one (for example, closing
313 * and re-opening the same experiment should not retrigger building
314 * all supplementary files).
316 tracesToSynchronize
.forEach(t
-> {
317 long offset
= checkNotNull(offsetGetter
.apply(t
));
318 long delta
= average
- offset
;
320 ITmfTrace trace
= (ITmfTrace
) t
;
321 ITmfTimestampTransform currentTransform
= trace
.getTimestampTransform();
322 ITmfTimestampTransform newTransform
= TimestampTransformFactory
.createWithOffset(delta
);
324 if (!newTransform
.equals(currentTransform
)) {
325 TmfTraceManager
.deleteSupplementaryFiles(trace
);
326 trace
.setTimestampTransform(newTransform
);
333 public IStatus
validate(final IProject project
, final String path
) {
334 return Status
.OK_STATUS
;
337 // ------------------------------------------------------------------------
339 // ------------------------------------------------------------------------
342 * Get the traces contained in this experiment.
344 * @return The array of contained traces
346 public List
<@NonNull ITmfTrace
> getTraces() {
347 return getChildren(ITmfTrace
.class);
351 * Returns the timestamp of the event at the requested index. If none,
355 * the event index (rank)
356 * @return the corresponding event timestamp
358 public ITmfTimestamp
getTimestamp(final int index
) {
359 final ITmfContext context
= seekEvent(index
);
360 final ITmfEvent event
= getNext(context
);
362 return (event
!= null) ? event
.getTimestamp() : null;
365 // ------------------------------------------------------------------------
366 // Request management
367 // ------------------------------------------------------------------------
370 public synchronized ITmfContext
armRequest(final ITmfEventRequest request
) {
372 // Make sure we have something to read from
373 if (getChildren().isEmpty()) {
377 if (!TmfTimestamp
.BIG_BANG
.equals(request
.getRange().getStartTime())
378 && request
.getIndex() == 0) {
379 final ITmfContext context
= seekEvent(request
.getRange().getStartTime());
380 request
.setStartIndex((int) context
.getRank());
385 return seekEvent(request
.getIndex());
388 // ------------------------------------------------------------------------
389 // ITmfTrace trace positioning
390 // ------------------------------------------------------------------------
393 public synchronized ITmfContext
seekEvent(final ITmfLocation location
) {
394 // Validate the location
395 if (location
!= null && !(location
instanceof TmfExperimentLocation
)) {
396 return null; // Throw an exception?
399 int length
= getNbChildren();
401 // Initialize the location array if necessary
402 TmfLocationArray locationArray
= ((location
== null) ?
new TmfLocationArray(length
) : ((TmfExperimentLocation
) location
).getLocationInfo());
404 ITmfLocation
[] locations
= locationArray
.getLocations();
405 long[] ranks
= locationArray
.getRanks();
407 // Create and populate the context's traces contexts
408 final TmfExperimentContext context
= new TmfExperimentContext(length
);
410 // Position the traces
412 for (int i
= 0; i
< length
; i
++) {
413 // Get the relevant trace attributes
414 final ITmfContext traceContext
= ((ITmfTrace
) getChild(i
)).seekEvent(locations
[i
]);
415 context
.setContext(i
, traceContext
);
416 traceContext
.setRank(ranks
[i
]);
417 // update location after seek
418 locations
[i
] = traceContext
.getLocation();
419 context
.setEvent(i
, ((ITmfTrace
) getChild(i
)).getNext(traceContext
));
424 context
.setLocation(new TmfExperimentLocation(new TmfLocationArray(locations
, ranks
)));
425 context
.setLastTrace(TmfExperimentContext
.NO_TRACE
);
426 context
.setRank(rank
);
431 // ------------------------------------------------------------------------
432 // ITmfTrace - SeekEvent operations (returning a trace context)
433 // ------------------------------------------------------------------------
436 public ITmfContext
seekEvent(final double ratio
) {
437 final ITmfContext context
= seekEvent(Math
.round(ratio
* getNbEvents()));
442 public double getLocationRatio(final ITmfLocation location
) {
443 if (location
instanceof TmfExperimentLocation
) {
445 TmfLocationArray locationArray
= ((TmfExperimentLocation
) location
).getLocationInfo();
446 for (int i
= 0; i
< locationArray
.size(); i
++) {
447 rank
+= locationArray
.getRank(i
);
449 return (double) rank
/ getNbEvents();
455 public ITmfLocation
getCurrentLocation() {
460 // ------------------------------------------------------------------------
461 // ITmfTrace trace positioning
462 // ------------------------------------------------------------------------
465 public synchronized ITmfEvent
parseEvent(final ITmfContext context
) {
466 final ITmfContext tmpContext
= seekEvent(context
.getLocation());
467 final ITmfEvent event
= getNext(tmpContext
);
472 public synchronized ITmfEvent
getNext(ITmfContext context
) {
474 // Validate the context
475 if (!(context
instanceof TmfExperimentContext
)) {
476 return null; // Throw an exception?
479 int length
= getNbChildren();
481 // Make sure that we have something to read from
486 TmfExperimentContext expContext
= (TmfExperimentContext
) context
;
488 // If an event was consumed previously, first get the next one from that
490 final int lastTrace
= expContext
.getLastTrace();
491 if (lastTrace
!= TmfExperimentContext
.NO_TRACE
) {
492 final ITmfContext traceContext
= expContext
.getContext(lastTrace
);
493 expContext
.setEvent(lastTrace
, ((ITmfTrace
) getChild(lastTrace
)).getNext(traceContext
));
494 expContext
.setLastTrace(TmfExperimentContext
.NO_TRACE
);
497 // Scan the candidate events and identify the "next" trace to read from
498 int trace
= TmfExperimentContext
.NO_TRACE
;
499 ITmfTimestamp timestamp
= TmfTimestamp
.BIG_CRUNCH
;
500 for (int i
= 0; i
< length
; i
++) {
501 final ITmfEvent event
= expContext
.getEvent(i
);
504 final ITmfTimestamp otherTS
= event
.getTimestamp();
505 if (otherTS
.compareTo(timestamp
) < 0) {
512 ITmfEvent event
= null;
513 if (trace
!= TmfExperimentContext
.NO_TRACE
) {
514 event
= expContext
.getEvent(trace
);
516 updateAttributes(expContext
, event
);
517 expContext
.increaseRank();
518 expContext
.setLastTrace(trace
);
519 final ITmfContext traceContext
= expContext
.getContext(trace
);
520 if (traceContext
== null) {
521 throw new IllegalStateException();
524 // Update the experiment location
525 ITmfLocation location
= expContext
.getLocation();
526 if (location
instanceof TmfExperimentLocation
) {
527 TmfLocationArray locationArray
= new TmfLocationArray(
528 ((TmfExperimentLocation
) location
).getLocationInfo(),
529 trace
, traceContext
.getLocation(), traceContext
.getRank());
530 expContext
.setLocation(new TmfExperimentLocation(locationArray
));
539 public ITmfTimestamp
getInitialRangeOffset() {
541 List
<ITmfTrace
> children
= getChildren(ITmfTrace
.class);
543 if (children
.isEmpty()) {
544 return super.getInitialRangeOffset();
547 ITmfTimestamp initTs
= TmfTimestamp
.BIG_CRUNCH
;
548 for (ITmfTrace trace
: children
) {
549 ITmfTimestamp ts
= (trace
).getInitialRangeOffset();
550 if (ts
.compareTo(initTs
) < 0) {
558 * Get the path to the folder in the supplementary file where
559 * synchronization-related data can be kept so they are not deleted when the
560 * experiment is synchronized. Analysis involved in synchronization can put
561 * their supplementary files in there so they are preserved after
564 * If the directory does not exist, it will be created. A return value of
565 * <code>null</code> means either the trace resource does not exist or
566 * supplementary resources cannot be kept.
569 * If <code>true</code>, it returns the absolute path in the file
570 * system, including the supplementary file path. Otherwise, it
571 * returns only the directory name.
572 * @return The path to the folder where synchronization-related
573 * supplementary files can be kept or <code>null</code> if not
576 public String
getSynchronizationFolder(boolean absolute
) {
577 /* Set up the path to the synchronization file we'll use */
578 IResource resource
= this.getResource();
579 String syncDirectory
= null;
582 /* get the directory where the file will be stored. */
583 if (resource
!= null) {
584 String fullDirectory
= resource
.getPersistentProperty(TmfCommonConstants
.TRACE_SUPPLEMENTARY_FOLDER
);
585 /* Create the synchronization data directory if not present */
586 if (fullDirectory
!= null) {
587 fullDirectory
= fullDirectory
+ File
.separator
+ SYNCHRONIZATION_DIRECTORY
;
588 File syncDir
= new File(fullDirectory
);
592 syncDirectory
= fullDirectory
;
594 syncDirectory
= SYNCHRONIZATION_DIRECTORY
;
597 } catch (CoreException e
) {
601 return syncDirectory
;
605 * Synchronizes the traces of an experiment. By default it only tries to
606 * read a synchronization file if it exists
608 * @return The synchronization object
610 public SynchronizationAlgorithm
synchronizeTraces() {
611 return synchronizeTraces(false);
615 * Synchronizes the traces of an experiment.
618 * Whether to actually synchronize or just try opening a sync
620 * @return The synchronization object
622 public SynchronizationAlgorithm
synchronizeTraces(boolean doSync
) {
626 String syncDirectory
= getSynchronizationFolder(true);
628 final File syncFile
= (syncDirectory
!= null) ?
new File(syncDirectory
+ File
.separator
+ SYNCHRONIZATION_FILE_NAME
) : null;
630 final SynchronizationAlgorithm syncAlgo
= SynchronizationManager
.synchronizeTraces(syncFile
, Collections
.singleton(this), doSync
);
632 final TmfTraceSynchronizedSignal signal
= new TmfTraceSynchronizedSignal(this, syncAlgo
);
634 /* Broadcast in separate thread to prevent deadlock */
649 @SuppressWarnings("nls")
650 public synchronized String
toString() {
651 return "[TmfExperiment (" + getName() + ")]";
654 // ------------------------------------------------------------------------
656 // ------------------------------------------------------------------------
658 private synchronized void initializeStreamingMonitor() {
665 if (getStreamingInterval() == 0) {
666 final ITmfContext context
= seekEvent(0);
667 final ITmfEvent event
= getNext(context
);
672 final TmfTimeRange timeRange
= new TmfTimeRange(event
.getTimestamp(), TmfTimestamp
.BIG_CRUNCH
);
673 final TmfTraceRangeUpdatedSignal signal
= new TmfTraceRangeUpdatedSignal(this, this, timeRange
);
675 // Broadcast in separate thread to prevent deadlock
685 final Thread thread
= new Thread("Streaming Monitor for experiment " + getName()) { //$NON-NLS-1$
686 private ITmfTimestamp safeTimestamp
= null;
687 private ITmfTimestamp lastSafeTimestamp
= null;
688 private TmfTimeRange timeRange
= null;
692 while (!executorIsShutdown()) {
693 if (!getIndexer().isIndexing()) {
694 ITmfTimestamp startTimestamp
= TmfTimestamp
.BIG_CRUNCH
;
695 ITmfTimestamp endTimestamp
= TmfTimestamp
.BIG_BANG
;
697 for (final ITmfTrace trace
: getChildren(ITmfTrace
.class)) {
698 if (trace
.getStartTime().compareTo(startTimestamp
) < 0) {
699 startTimestamp
= trace
.getStartTime();
701 if (trace
.getStreamingInterval() != 0 && trace
.getEndTime().compareTo(endTimestamp
) > 0) {
702 endTimestamp
= trace
.getEndTime();
705 ITmfTimestamp safeTs
= safeTimestamp
;
706 if (safeTs
!= null && (lastSafeTimestamp
== null || safeTs
.compareTo(lastSafeTimestamp
) > 0)) {
707 timeRange
= new TmfTimeRange(startTimestamp
, safeTs
);
708 lastSafeTimestamp
= safeTs
;
712 safeTimestamp
= endTimestamp
;
713 if (timeRange
!= null) {
714 final TmfTraceRangeUpdatedSignal signal
= new TmfTraceRangeUpdatedSignal(TmfExperiment
.this, TmfExperiment
.this, timeRange
);
719 Thread
.sleep(getStreamingInterval());
720 } catch (final InterruptedException e
) {
730 public long getStreamingInterval() {
732 for (final ITmfTrace trace
: getChildren(ITmfTrace
.class)) {
733 interval
= Math
.max(interval
, trace
.getStreamingInterval());
738 // ------------------------------------------------------------------------
740 // ------------------------------------------------------------------------
744 public void traceOpened(TmfTraceOpenedSignal signal
) {
745 if (signal
.getTrace() == this) {
746 initializeStreamingMonitor();
748 /* Initialize the analysis */
749 MultiStatus status
= new MultiStatus(Activator
.PLUGIN_ID
, IStatus
.OK
, null, null);
750 status
.add(executeAnalysis());
751 if (!status
.isOK()) {
752 Activator
.log(status
);
754 TmfTraceManager
.refreshSupplementaryFiles(this);
759 public synchronized int getCheckpointSize() {
760 int totalCheckpointSize
= 0;
762 List
<ITmfTrace
> children
= getChildren(ITmfTrace
.class);
763 for (ITmfTrace trace
: children
) {
764 if (!(trace
instanceof ITmfPersistentlyIndexable
)) {
768 ITmfPersistentlyIndexable persistableIndexTrace
= (ITmfPersistentlyIndexable
) trace
;
769 int currentTraceCheckpointSize
= persistableIndexTrace
.getCheckpointSize();
770 if (currentTraceCheckpointSize
<= 0) {
773 totalCheckpointSize
+= currentTraceCheckpointSize
;
774 // each entry in the TmfLocationArray has a rank in addition
776 totalCheckpointSize
+= 8;
778 } catch (UnsupportedOperationException e
) {
782 return totalCheckpointSize
;
786 public ITmfLocation
restoreLocation(ByteBuffer bufferIn
) {
787 List
<ITmfTrace
> children
= getChildren(ITmfTrace
.class);
788 int length
= children
.size();
789 ITmfLocation
[] locations
= new ITmfLocation
[length
];
790 long[] ranks
= new long[length
];
791 for (int i
= 0; i
< length
; ++i
) {
792 final ITmfTrace trace
= children
.get(i
);
793 locations
[i
] = ((ITmfPersistentlyIndexable
) trace
).restoreLocation(bufferIn
);
794 ranks
[i
] = bufferIn
.getLong();
796 TmfLocationArray arr
= new TmfLocationArray(locations
, ranks
);
797 TmfExperimentLocation l
= new TmfExperimentLocation(arr
);