package org.eclipse.tracecompass.tmf.ctf.core.trace;
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString;
+import java.io.File;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
+import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.process.ProcessUtils;
import org.eclipse.tracecompass.ctf.core.CTFException;
import org.eclipse.tracecompass.ctf.core.event.CTFClock;
import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
import org.eclipse.tracecompass.tmf.core.event.TmfEventField;
-import org.eclipse.tracecompass.tmf.core.event.aspect.TmfBaseAspects;
import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
+import org.eclipse.tracecompass.tmf.core.event.aspect.TmfBaseAspects;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
import org.eclipse.tracecompass.tmf.core.project.model.ITmfPropertiesProvider;
import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat;
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.indexer.checkpoint.ITmfCheckpoint;
import org.eclipse.tracecompass.tmf.core.trace.indexer.checkpoint.TmfCheckpoint;
import org.eclipse.tracecompass.tmf.core.trace.location.ITmfLocation;
+import org.eclipse.tracecompass.tmf.core.trace.trim.ITmfTrimmableTrace;
import org.eclipse.tracecompass.tmf.ctf.core.CtfConstants;
import org.eclipse.tracecompass.tmf.ctf.core.context.CtfLocation;
import org.eclipse.tracecompass.tmf.ctf.core.context.CtfLocationInfo;
*/
public class CtfTmfTrace extends TmfTrace
implements ITmfPropertiesProvider, ITmfPersistentlyIndexable,
- ITmfTraceWithPreDefinedEvents, ITmfTraceKnownSize {
+ ITmfTraceWithPreDefinedEvents, ITmfTraceKnownSize, ITmfTrimmableTrace {
// -------------------------------------------
// Constants
private static final int CONFIDENCE = 10;
private static final int MIN_CONFIDENCE = 1;
+ /** Timestamp formatter to pass to Babeltrace */
+ private static final TmfTimestampFormat TS_FORMAT = new TmfTimestampFormat("T.SSSSSSSSS"); //$NON-NLS-1$
+
/**
* This is a reduction factor to avoid overflows.
*/
public int progress() {
return (int) (getNbEvents() / REDUCTION_FACTOR);
}
+
+ /**
+ * @since 2.2
+ */
+ @Override
+ @SuppressWarnings("nls")
+ public void trim(@NonNull TmfTimeRange range, @NonNull Path destinationPath, @NonNull IProgressMonitor monitor) throws CoreException {
+ List<@NonNull String> command;
+ @Nullable List<String> output;
+
+ /* Verify that Babeltrace 2.0 is installed and available */
+ command = Arrays.asList("babeltrace", "--version");
+ output = ProcessUtils.getOutputFromCommand(command);
+ if (output == null || output.isEmpty() || !output.get(0).contains("Babeltrace 2")) {
+ IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.CtfTmfTrace_BabelTrace2NotFound);
+ throw new CoreException(status);
+ }
+
+ /* Trim and save the new trace */
+ String originPath = getPath();
+ if (!originPath.endsWith(File.separator)) {
+ originPath = originPath + File.separator;
+ }
+
+ String rangeStart = TS_FORMAT.format(range.getStartTime().toNanos());
+ String rangeEnd = TS_FORMAT.format(range.getEndTime().toNanos());
+
+ command = Arrays.asList("bash", "-c",
+ "babeltrace"
+ + " \"" + originPath + "\""
+ + " --begin " + rangeStart
+ + " --end " + rangeEnd
+ /* Ignore Babeltrace's debug info generation, we have our own */
+ + " --no-debug-info"
+ + " --component sink.ctf.fs"
+ + " --path \"" + destinationPath.toString() + '\"'
+ /*
+ * This option outputs the trace exactly in the directory we specify, without
+ * creating a hierarchy from the host/trace names. Note that it only works if
+ * there is a single trace as input. It would not work with an experiment.
+ */
+ + " -p single-trace=true"
+ );
+
+ ProcessUtils.getOutputFromCommandCancellable(command,
+ monitor,
+ nullToEmptyString(Messages.CtfTmfTrace_InvokingBabeltrace),
+ /* We don't need to process the output. */
+ (r, m) -> Collections.emptyList());
+ }
+
}