blob: 93beb356f8b749ea2ac4b79845aff9c2813f6a96 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Ericsson
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.incubator.internal.ftrace.core.trace;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.incubator.internal.ftrace.core.Activator;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
import org.eclipse.tracecompass.tmf.core.project.model.ITmfPropertiesProvider;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
import org.eclipse.tracecompass.tmf.core.trace.TraceValidationStatus;
/**
* Helper to open fTrace traces
*
* @author Matthew Khouzam
*
*/
public class BinaryFTrace extends GenericFtrace implements ITmfPropertiesProvider {
private static final String TRACE_CMD = "trace-cmd"; //$NON-NLS-1$
private static final String REPORT = "report"; //$NON-NLS-1$
private final @NonNull Map<@NonNull String, @NonNull String> fProperties = new LinkedHashMap<>();
@Override
public IStatus validate(IProject project, String path) {
File file = new File(path);
if (!file.exists()) {
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "File not found: " + path); //$NON-NLS-1$
}
if (!file.isFile()) {
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Not a file. It's a directory: " + path); //$NON-NLS-1$
}
int confidence = 32;
try {
if (!TmfTraceUtils.isText(file)) {
int magicLength = TRACE_CMD_DAT_MAGIC.length;
if (file.length() > magicLength) {
try (FileInputStream fis = new FileInputStream(file)) {
byte[] start = new byte[magicLength];
int read = fis.read(start);
if (read == magicLength && Arrays.equals(TRACE_CMD_DAT_MAGIC, start)) {
ProcessBuilder pb = new ProcessBuilder(TRACE_CMD);
Process traceCmd = pb.start();
try (BufferedReader br = new BufferedReader(new InputStreamReader(traceCmd.getInputStream(), Charset.forName("UTF-8")));) { //$NON-NLS-1$
String line = br.readLine();
while (line != null) {
if (line.contains(REPORT)) {
return new TraceValidationStatus(confidence, Activator.PLUGIN_ID);
}
line = br.readLine();
}
}
}
}
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Magic mismatch"); //$NON-NLS-1$
}
}
} catch (IOException e) {
Activator.getInstance().logError("Error validating file: " + path, e); //$NON-NLS-1$
if (e.getMessage().startsWith("Cannot run program: \"" + TRACE_CMD + "\": error=2,")) { //$NON-NLS-1$ //$NON-NLS-2$
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "It appears trace-cmd is not available on your machine. Please install it to use the binary ftrace parser. (sudo apt install trace-cmd)", e); //$NON-NLS-1$
}
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "IOException validating file: " + path, e); //$NON-NLS-1$
}
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Not an FTrace bin"); //$NON-NLS-1$
}
@Override
public void initTrace(IResource resource, String path, Class<? extends ITmfEvent> type, String name, String traceTypeId) throws TmfTraceException {
super.initTrace(resource, path, type, name, traceTypeId);
fProperties.put("Type", "Trace-Event"); //$NON-NLS-1$ //$NON-NLS-2$
String dir = TmfTraceManager.getSupplementaryFileDir(this);
if (!new File(dir).exists()) {
throw new TmfTraceException("Could not create temporary folder " + dir); //$NON-NLS-1$
}
File file = new File(dir + new File(path).getName());
if (!file.exists()) {
ProcessBuilder pb = new ProcessBuilder(TRACE_CMD, "report", "-i", path, "-R"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
pb.redirectOutput(file);
try {
pb.start().waitFor();
} catch (IOException | InterruptedException e) {
throw new TmfTraceException(e.getMessage(), e);
}
if (!file.exists()) {
throw new TmfTraceException("Could not create temporary file " + file.getAbsolutePath()); //$NON-NLS-1$
}
if (file.length() <= 0) {
throw new TmfTraceException("Empty temporary file " + file.getAbsolutePath()); //$NON-NLS-1$
}
}
setFile(file);
}
@Override
public @NonNull Map<@NonNull String, @NonNull String> getProperties() {
return fProperties;
}
}