package org.eclipse.tracecompass.internal.analysis.os.linux.core.latency;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.datastore.core.interval.IHTIntervalReader;
+import org.eclipse.tracecompass.datastore.core.serialization.ISafeByteBufferWriter;
+import org.eclipse.tracecompass.datastore.core.serialization.SafeByteBufferFactory;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.segmentstore.core.segment.interfaces.INamedSegment;
private static final long serialVersionUID = 1554494342105208730L;
+ /**
+ * The reader for this segment class
+ */
+ public static final IHTIntervalReader<ISegment> READER = buffer -> new SystemCall(buffer.getLong(), buffer.getLong(), buffer.getString());
+
/**
* The subset of information that is available from the syscall entry event.
*/
}
}
- private long fStartTime;
- private long fEndTime;
- private String fName;
+ private final long fStartTime;
+ private final long fEndTime;
+ private final String fName;
/**
* @param info
fEndTime = endTime;
}
- private void writeObject(ObjectOutputStream out) throws IOException {
- out.writeLong(fStartTime);
- out.writeLong(fEndTime);
- out.writeUTF(fName);
- }
-
- private void readObject(ObjectInputStream in) throws IOException {
- fStartTime = in.readLong();
- fEndTime = in.readLong();
- fName = in.readUTF().intern();
+ private SystemCall(long startTime, long endTime, String name) {
+ fStartTime = startTime;
+ fEndTime = endTime;
+ fName = name;
}
@Override
return fName;
}
+ @Override
+ public int getSizeOnDisk() {
+ return 2 * Long.BYTES + SafeByteBufferFactory.getStringSizeInBuffer(fName);
+ }
+
+ @Override
+ public void writeSegment(@NonNull ISafeByteBufferWriter buffer) {
+ buffer.putLong(fStartTime);
+ buffer.putLong(fEndTime);
+ buffer.putString(fName);
+ }
+
@Override
public int compareTo(@NonNull ISegment o) {
int ret = INamedSegment.super.compareTo(o);
"; Duration = " + getLength() + //$NON-NLS-1$
"; Name = " + getName(); //$NON-NLS-1$
}
+
}
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisEventBasedModule;
+import org.eclipse.tracecompass.datastore.core.interval.IHTIntervalReader;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
+import org.eclipse.tracecompass.segmentstore.core.SegmentStoreFactory.SegmentStoreType;
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect;
*/
public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.latency.syscall"; //$NON-NLS-1$
- private static final String DATA_FILENAME = "latency-analysis.dat"; //$NON-NLS-1$
-
private static final Collection<ISegmentAspect> BASE_ASPECTS =
ImmutableList.of(SyscallNameAspect.INSTANCE);
}
@Override
- public @NonNull String getDataFileName() {
- return DATA_FILENAME;
+ protected @NonNull SegmentStoreType getSegmentStoreType() {
+ return SegmentStoreType.OnDisk;
}
@Override
- public AbstractSegmentStoreAnalysisRequest createAnalysisRequest(ISegmentStore<ISegment> syscalls) {
+ protected AbstractSegmentStoreAnalysisRequest createAnalysisRequest(ISegmentStore<ISegment> syscalls) {
return new SyscallLatencyAnalysisRequest(syscalls);
}
+ @Override
+ protected @NonNull IHTIntervalReader<ISegment> getSegmentReader() {
+ return SystemCall.READER;
+ }
+
+ @Deprecated
@Override
protected Object[] readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
return checkNotNull((Object[]) ois.readObject());
}
long endTime = event.getTimestamp().toNanos();
- ISegment syscall = new SystemCall(info, endTime);
+ SystemCall syscall = new SystemCall(info, endTime);
getSegmentStore().add(syscall);
}
}
import java.io.IOException;
import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.datastore.core.interval.IHTIntervalReader;
+import org.eclipse.tracecompass.internal.analysis.timing.core.Activator;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
import org.eclipse.tracecompass.segmentstore.core.SegmentStoreFactory;
+import org.eclipse.tracecompass.segmentstore.core.SegmentStoreFactory.SegmentStoreType;
import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect;
*/
public abstract class AbstractSegmentStoreAnalysisModule extends TmfAbstractAnalysisModule implements ISegmentStoreProvider {
+ private static final String EXTENSION = ".ss"; //$NON-NLS-1$
private final ListenerList fListeners = new ListenerList(ListenerList.IDENTITY);
private @Nullable ISegmentStore<ISegment> fSegmentStore;
/**
* Returns the file name for storing segment store
*
- * @return segment store fine name, or null if you don't want a file
+ * @return segment store file name
*/
- protected @Nullable String getDataFileName() {
- return null;
+ protected String getDataFileName() {
+ return getId() + EXTENSION;
}
/**
* - Class of a serialized object cannot be found.
* @throws IOException
* - Any of the usual Input/Output related exceptions.
+ * @deprecated The segment store analysis modules are either on disk or all
+ * in memory, no in between anymore
*/
+ @Deprecated
protected abstract Object[] readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException;
/**
*/
protected abstract boolean buildAnalysisSegments(ISegmentStore<ISegment> segmentStore, IProgressMonitor monitor) throws TmfAnalysisException;
+ /**
+ * Get the reader for the segments on disk. If the segment store is not on
+ * disk, this method can return null.
+ *
+ * @return The segment reader
+ * @since 3.0
+ */
+ protected IHTIntervalReader<ISegment> getSegmentReader() {
+ throw new UnsupportedOperationException("getSegmentReader: This method should be overriden in classes that saves the segment store on disk"); //$NON-NLS-1$
+ }
+
+ /**
+ * Get the type of segment store to build. By default it is
+ * {@link SegmentStoreType#Fast}
+ *
+ * @return The type of segment store to build
+ * @since 3.0
+ */
+ protected SegmentStoreType getSegmentStoreType() {
+ return SegmentStoreType.Fast;
+ }
+
@Override
public @Nullable ISegmentStore<ISegment> getSegmentStore() {
return fSegmentStore;
@Override
protected boolean executeAnalysis(IProgressMonitor monitor) throws TmfAnalysisException {
+ SegmentStoreType type = getSegmentStoreType();
+ ISegmentStore<ISegment> store = null;
+ switch (type) {
+ case Distinct:
+ // Fall-through
+ case Fast:
+ // Fall-through
+ case Stable:
+ store = buildInMemorySegmentStore(type, monitor);
+ break;
+ case OnDisk:
+ final @Nullable String dataFileName = getDataFileName();
+ store = buildOnDiskSegmentStore(dataFileName, monitor);
+ break;
+ default:
+ Activator.getInstance().logError("Unknown segment store type: " + type); //$NON-NLS-1$
+ break;
+ }
+
+ if (store == null) {
+ return false;
+ }
+
+ fSegmentStore = store;
+ sendUpdate(store);
+ return true;
+ }
+
+ private @Nullable ISegmentStore<@NonNull ISegment> buildOnDiskSegmentStore(@Nullable String dataFileName, IProgressMonitor monitor) throws TmfAnalysisException {
ITmfTrace trace = checkNotNull(getTrace());
- final @Nullable String dataFileName = getDataFileName();
- if (dataFileName != null) {
- /* See if the data file already exists on disk */
- String dir = TmfTraceManager.getSupplementaryFileDir(trace);
- final Path file = Paths.get(dir, dataFileName);
-
- if (Files.exists(file)) {
- /* Attempt to read the existing file */
- try (ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(file))) {
- Object[] segmentArray = readObject(ois);
- ISegmentStore<ISegment> store = SegmentStoreFactory.createSegmentStore(NonNullUtils.checkNotNullContents(segmentArray));
- fSegmentStore = store;
- sendUpdate(store);
- return true;
- } catch (IOException | ClassNotFoundException | ClassCastException e) {
- /*
- * We did not manage to read the file successfully, we will
- * just fall-through to rebuild a new one.
- */
- try {
- Files.delete(file);
- } catch (IOException e1) {
- }
- }
+ String fileName = dataFileName;
+ if (fileName == null) {
+ fileName = getId() + ".ss"; //$NON-NLS-1$
+ }
+ /* See if the data file already exists on disk */
+ String dir = TmfTraceManager.getSupplementaryFileDir(trace);
+ final Path file = Paths.get(dir, fileName);
+
+ boolean built = false;
+ ISegmentStore<ISegment> segmentStore;
+ try {
+ // Compare the file creation time to determine if this analysis is
+ // built from scratch or not
+ FileTime origCreationTime = (Files.exists(file) ? NonNullUtils.checkNotNull(Files.readAttributes(file, BasicFileAttributes.class)).creationTime() : FileTime.fromMillis(0));
+ segmentStore = SegmentStoreFactory.createOnDiskSegmentStore(file, getSegmentReader());
+ FileTime creationTime = NonNullUtils.checkNotNull(Files.readAttributes(file, BasicFileAttributes.class)).creationTime();
+ built = origCreationTime.equals(creationTime);
+ } catch (IOException e) {
+ try {
+ Files.deleteIfExists(file);
+ } catch (IOException e1) {
+ // Ignore
}
+ Activator.getInstance().logError("Error creating segment store", e); //$NON-NLS-1$
+ return null;
}
- ISegmentStore<ISegment> segmentStore = SegmentStoreFactory.createSegmentStore();
+ if (built) {
+ return segmentStore;
+ }
boolean completed = buildAnalysisSegments(segmentStore, monitor);
if (!completed) {
- return false;
- }
- fSegmentStore = segmentStore;
-
- if (dataFileName != null) {
- String dir = TmfTraceManager.getSupplementaryFileDir(trace);
- final Path file = Paths.get(dir, dataFileName);
-
- /* Serialize the collections to disk for future usage */
- try (ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(file))) {
- oos.writeObject(segmentStore.toArray());
- } catch (IOException e) {
- /*
- * Didn't work, oh well. We will just re-read the trace next
- * time
- */
- }
+ return null;
}
- sendUpdate(segmentStore);
+ return segmentStore;
+ }
- return true;
+ private @Nullable ISegmentStore<@NonNull ISegment> buildInMemorySegmentStore(SegmentStoreType type, IProgressMonitor monitor) throws TmfAnalysisException {
+ ISegmentStore<ISegment> segmentStore = SegmentStoreFactory.createSegmentStore(type);
+ boolean completed = buildAnalysisSegments(segmentStore, monitor);
+ if (!completed) {
+ return null;
+ }
+
+ return segmentStore;
}
/**