import org.eclipse.tracecompass.ctf.core.event.CTFClock;
import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInput;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
import org.eclipse.tracecompass.ctf.core.trace.CTFTraceReader;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
import org.eclipse.tracecompass.ctf.core.trace.Metadata;
import org.eclipse.tracecompass.internal.tmf.ctf.core.Activator;
import org.eclipse.tracecompass.internal.tmf.ctf.core.trace.iterator.CtfIterator;
import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceKnownSize;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceWithPreDefinedEvents;
import org.eclipse.tracecompass.tmf.core.trace.TmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TraceValidationStatus;
*/
public class CtfTmfTrace extends TmfTrace
implements ITmfPropertiesProvider, ITmfPersistentlyIndexable,
- ITmfTraceWithPreDefinedEvents {
+ ITmfTraceWithPreDefinedEvents, ITmfTraceKnownSize {
// -------------------------------------------
// Constants
/**
* Clock offset property
+ *
* @since 1.2
*/
public static final String CLOCK_OFFSET = "clock_offset"; //$NON-NLS-1$
/**
* Event aspects available for all CTF traces
+ *
* @since 1.0
*/
- protected static final @NonNull Collection<@NonNull ITmfEventAspect<?>> CTF_ASPECTS =
- ImmutableList.of(
- TmfBaseAspects.getTimestampAspect(),
- new CtfChannelAspect(),
- new CtfCpuAspect(),
- TmfBaseAspects.getEventTypeAspect(),
- TmfBaseAspects.getContentsAspect()
- );
+ protected static final @NonNull Collection<@NonNull ITmfEventAspect<?>> CTF_ASPECTS = ImmutableList.of(
+ TmfBaseAspects.getTimestampAspect(),
+ new CtfChannelAspect(),
+ new CtfCpuAspect(),
+ TmfBaseAspects.getEventTypeAspect(),
+ TmfBaseAspects.getContentsAspect());
/**
* The Ctf clock unique identifier field
private static final int CONFIDENCE = 10;
private static final int MIN_CONFIDENCE = 1;
+ /**
+ * This is a reduction factor to avoid overflows.
+ */
+ private static final long REDUCTION_FACTOR = 4096;
+
+ /**
+ * Average CTF event size, used to estimate the trace size. (Inspired by
+ * empirical observations with LTTng kernel traces, to avoid hanging at 100%
+ * for too long)
+ *
+ * TODO: Find a more suitable approximation, perhaps per concrete trace type
+ * or per trace directly with the metadata
+ */
+ private static final int CTF_AVG_EVENT_SIZE = 16;
+
// -------------------------------------------
// Fields
// -------------------------------------------
- private final Map<@NonNull String, @NonNull CtfTmfEventType> fContainedEventTypes =
- Collections.synchronizedMap(new HashMap<>());
+ private final Map<@NonNull String, @NonNull CtfTmfEventType> fContainedEventTypes = Collections.synchronizedMap(new HashMap<>());
private final CtfIteratorManager fIteratorManager = new CtfIteratorManager(this);
* Firstly a weak validation of the metadata is done to determine if the
* path is actually for a CTF trace. After that a full validation is done.
*
- * If the weak and full validation are successful the confidence is set
- * to 10.
+ * If the weak and full validation are successful the confidence is set to
+ * 10.
*
- * If the weak validation was successful, but the full validation fails
- * a TraceValidationStatus with severity warning and confidence of 1 is
+ * If the weak validation was successful, but the full validation fails a
+ * TraceValidationStatus with severity warning and confidence of 1 is
* returned.
*
* If both weak and full validation fails an error status is returned.
}
// Validate using reader initialization
- try (CTFTraceReader ctfTraceReader = new CTFTraceReader(trace)) {}
+ try (CTFTraceReader ctfTraceReader = new CTFTraceReader(trace)) {
+ // do nothing
+ }
// Trace is validated, return with confidence
return new CtfTraceValidationStatus(CONFIDENCE, Activator.PLUGIN_ID, trace.getEnvironment());
- } catch (final CTFException | BufferOverflowException e ) {
+ } catch (final CTFException | BufferOverflowException e) {
// return warning since it's a CTF trace but with errors in it
return new TraceValidationStatus(MIN_CONFIDENCE, IStatus.WARNING, Activator.PLUGIN_ID, Messages.CtfTmfTrace_ReadingError + ": " + e.toString(), e); //$NON-NLS-1$
}
Activator.getDefault().logError(e.getMessage(), e);
}
}
+
+ /**
+ * @return the number of estimated chunks of events read. This reads the
+ * file size of the trace and divides it by a factor and the average
+ * event size, this is not accurate but can give a ball park figure
+ * of how much is done.
+ * @since 2.1
+ */
+ @Override
+ public int size() {
+ long size = 0;
+ Iterable<ICTFStream> streams = fTrace.getStreams();
+ for (ICTFStream stream : streams) {
+ for (CTFStreamInput si : stream.getStreamInputs()) {
+ size += si.getFile().length();
+ }
+ }
+ return (int) (size / REDUCTION_FACTOR / CTF_AVG_EVENT_SIZE);
+ }
+
+ /**
+ * @return the number of events divided a reduction factor. Is monotonic.
+ * @since 2.1
+ */
+ @Override
+ public int progress() {
+ return (int) (getNbEvents() / REDUCTION_FACTOR);
+ }
}
--- /dev/null
+/**********************************************************************
+ * Copyright (c) 2016 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ **********************************************************************/
+
+package org.eclipse.tracecompass.tmf.core.trace;
+
+/**
+ * An interface that trace classes can implement if they have a known size, so
+ * that reading progress can be shown.
+ *
+ * @author Matthew Khouzam
+ * @since 2.1
+ */
+public interface ITmfTraceKnownSize {
+ /**
+ * Get the size of the trace. The units of this value are not important, but
+ * they should always be the same as {@link #progress()}
+ *
+ * @return the size of the trace. This can change from one call to the
+ * other, but a later call to this method should not see a decrease
+ * in size.
+ */
+ int size();
+
+ /**
+ * How much of the trace is read. The units of this value are not important,
+ * but they should always be the same as {@link #size()}
+ *
+ * @return how much of the trace is read. This should not exceed
+ * {@link #size()}
+ */
+ int progress();
+}
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.internal.tmf.core.Activator;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceKnownSize;
import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfTraceIndexer;
import org.eclipse.tracecompass.tmf.core.trace.location.ITmfLocation;
private final class TmfIndexingJob extends Job {
private Exception fException = null;
+ private final ITmfTraceKnownSize fTraceWithSize;
private TmfIndexingJob(String name) {
super(name);
+ fTraceWithSize = (fTrace instanceof ITmfTraceKnownSize) ? (ITmfTraceKnownSize) fTrace : null;
}
@Override
protected IStatus run(final IProgressMonitor monitor) {
- monitor.beginTask("", IProgressMonitor.UNKNOWN); //$NON-NLS-1$
+ int alreadyDone = 0;
+ SubMonitor subMonitor = SubMonitor.convert(monitor);
+ if (fTraceWithSize != null) {
+ subMonitor.beginTask("", fTraceWithSize.size()); //$NON-NLS-1$
+ } else {
+ subMonitor.beginTask("", IProgressMonitor.UNKNOWN); //$NON-NLS-1$
+ }
while (!monitor.isCanceled()) {
try {
long prevNbEvents = fTrace.getNbEvents();
Thread.sleep(250);
long nbEvents = fTrace.getNbEvents();
+ if (fTraceWithSize != null) {
+ final int done = fTraceWithSize.progress();
+ subMonitor.setWorkRemaining(fTraceWithSize.size() - done);
+ subMonitor.worked(done - alreadyDone);
+ alreadyDone = done;
+ }
setName(Messages.TmfCheckpointIndexer_Indexing + ' ' + fTrace.getName() + " (" + String.format("%,d", nbEvents) + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
// setName doesn't refresh the UI, setTaskName does
long rate = (nbEvents - prevNbEvents) * 4;
- monitor.setTaskName(String.format("%,d", rate) + " " + Messages.TmfCheckpointIndexer_EventsPerSecond); //$NON-NLS-1$ //$NON-NLS-2$
+ subMonitor.setTaskName(String.format("%,d", rate) + " " + Messages.TmfCheckpointIndexer_EventsPerSecond); //$NON-NLS-1$ //$NON-NLS-2$
} catch (final InterruptedException e) {
return Status.OK_STATUS;
}
}
+ subMonitor.done();
monitor.done();
return fException != null ? new Status(IStatus.ERROR, Activator.PLUGIN_ID, fException.getMessage(), fException) : Status.OK_STATUS;
}