This allows a CTFStream to be shared while not being modifyiable.
Change-Id: I4bf4985abd5221ebfa543d0a7ff0cfeda0874fce
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/62767
Reviewed-by: Francis Giraldeau <francis.giraldeau@gmail.com>
Reviewed-by: Hudson CI
import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
import org.eclipse.tracecompass.ctf.core.trace.CTFResponse;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInput;
import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInputReader;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.junit.Before;
import org.junit.Test;
null,
"packet",
new Definition[] { new StringDefinition(StringDeclaration.getStringDeclaration(Encoding.UTF8), null, "field", "test") }),
- null)
- );
+ null));
}
private static CTFStreamInputReader getStreamInputReader() throws CTFException {
CTFTrace trace = CtfTestTraceUtils.getTrace(testTrace);
- CTFStream s = trace.getStream((long) 0);
+ ICTFStream s = trace.getStream((long) 0);
Set<CTFStreamInput> streamInput = s.getStreamInputs();
CTFStreamInputReader retVal = null;
for (CTFStreamInput si : streamInput) {
import org.eclipse.tracecompass.ctf.core.CTFException;
import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInput;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.junit.Before;
import org.junit.Test;
*/
@Test
public void testGetStream() {
- CTFStream result = fixture.getStream();
+ ICTFStream result = fixture.getStream();
assertNotNull(result);
}
import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInput;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.junit.Before;
import org.junit.Test;
import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.junit.Before;
import org.junit.Test;
@Test
public void testGetStream() {
Long id = new Long(0L);
- CTFStream result = fixture.getStream(id);
+ ICTFStream result = fixture.getStream(id);
assertNotNull(result);
}
import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.ISimpleDatatypeDeclaration;
import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
import org.eclipse.tracecompass.ctf.core.trace.Metadata;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.junit.Before;
protected CTFTrace testSingleFragment() throws CTFException {
fixture = new Metadata();
CTFTrace trace = fixture.getTrace();
- for (CTFStream s : trace.getStreams()) {
+ for (ICTFStream s : trace.getStreams()) {
fail("This should be empty, has" + s.toString());
}
fixture.parseText(mdStart);
int count = 0;
- for (CTFStream s : trace.getStreams()) {
+ for (ICTFStream s : trace.getStreams()) {
count++;
assertNotNull(s);
}
import org.eclipse.tracecompass.ctf.core.event.LostEventDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
import org.eclipse.tracecompass.ctf.core.trace.CTFTraceReader;
import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.junit.Before;
import org.junit.Test;
import org.eclipse.tracecompass.ctf.core.CTFException;
import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInputReader;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
/**
* Representation of one type of event. A bit like "int" or "long" but for trace
* Gets the {@link CTFStream} of an event declaration
*
* @return the stream
+ * @since 2.0
*/
- CTFStream getStream();
+ ICTFStream getStream();
/**
* What is the log level of this event?
import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInputReader;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
/**
* A lost event definition
return LOST_EVENT_ID;
}
+ /**
+ * @since 2.0
+ */
@Override
- public CTFStream getStream() {
+ public ICTFStream getStream() {
return null;
}
+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
- *
- * 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
- *
- * Contributors: Matthew Khouzam - Initial API and implementation
- * Contributors: Simon Marchi - Initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.tracecompass.ctf.core.trace;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.tracecompass.common.core.NonNullUtils;
-import org.eclipse.tracecompass.ctf.core.CTFException;
-import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
-
-/**
- * <b><u>Stream</u></b>
- * <p>
- * Represents a stream in a trace.
- */
-public class CTFStream {
-
- // ------------------------------------------------------------------------
- // Attributes
- // ------------------------------------------------------------------------
-
- /**
- * The numerical ID of the stream
- */
- private long fId = 0;
-
- /**
- * Declarations of the stream-specific structures
- */
- private StructDeclaration fPacketContextDecl = null;
- private IDeclaration fEventHeaderDecl = null;
- private StructDeclaration fEventContextDecl = null;
-
- /**
- * The trace to which the stream belongs
- */
- private CTFTrace fTrace = null;
-
- /**
- * Maps event ids to events
- */
- private final ArrayList<@Nullable IEventDeclaration> fEvents = new ArrayList<>();
-
- private boolean fEventUnsetId = false;
- private boolean fStreamIdSet = false;
-
- /**
- * The inputs associated to this stream
- */
- private final Set<CTFStreamInput> fInputs = new HashSet<>();
-
- // ------------------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------------------
-
- /**
- * Constructs a Stream that belongs to a Trace
- *
- * @param trace
- * The trace to which belongs this stream.
- */
- public CTFStream(CTFTrace trace) {
- fTrace = trace;
- }
-
- // ------------------------------------------------------------------------
- // Getters/Setters/Predicates
- // ------------------------------------------------------------------------
-
- /**
- * Sets the id of a stream
- *
- * @param id
- * the id of a stream
- */
- public void setId(long id) {
- fId = id;
- fStreamIdSet = true;
- }
-
- /**
- * Gets the id of a stream
- *
- * @return id the id of a stream
- * @since 1.0
- */
- public long getId() {
- return fId;
- }
-
- /**
- * Is the id of a stream set
- *
- * @return If the ID is set or not
- */
- public boolean isIdSet() {
- return fStreamIdSet;
- }
-
- /**
- *
- * @return is the event header set (timestamp and stuff) (see Ctf Spec)
- */
- public boolean isEventHeaderSet() {
- return fEventHeaderDecl != null;
- }
-
- /**
- *
- * @return is the event context set (pid and stuff) (see Ctf Spec)
- */
- public boolean isEventContextSet() {
- return fEventContextDecl != null;
- }
-
- /**
- *
- * @return Is the packet context set (see Ctf Spec)
- */
- public boolean isPacketContextSet() {
- return fPacketContextDecl != null;
- }
-
- /**
- * Sets the event header
- *
- * @param eventHeader
- * the current event header for all events in this stream
- */
- public void setEventHeader(StructDeclaration eventHeader) {
- fEventHeaderDecl = eventHeader;
- }
-
- /**
- * Sets the event header, this typically has the id and the timestamp
- *
- * @param eventHeader
- * the current event header for all events in this stream
- */
- public void setEventHeader(IEventHeaderDeclaration eventHeader) {
- fEventHeaderDecl = eventHeader;
- }
-
- /**
- *
- * @param eventContext
- * the context for all events in this stream
- */
- public void setEventContext(StructDeclaration eventContext) {
- fEventContextDecl = eventContext;
- }
-
- /**
- *
- * @param packetContext
- * the packet context for all packets in this stream
- */
- public void setPacketContext(StructDeclaration packetContext) {
- fPacketContextDecl = packetContext;
- }
-
- /**
- * Gets the event header declaration
- *
- * @return the event header declaration in declaration form
- */
- public IDeclaration getEventHeaderDeclaration() {
- return fEventHeaderDecl;
- }
-
- /**
- *
- * @return the event context declaration in structdeclaration form
- */
- public StructDeclaration getEventContextDecl() {
- return fEventContextDecl;
- }
-
- /**
- *
- * @return the packet context declaration in structdeclaration form
- */
- public StructDeclaration getPacketContextDecl() {
- return fPacketContextDecl;
- }
-
- /**
- *
- * @return the set of all stream inputs for this stream
- */
- public Set<CTFStreamInput> getStreamInputs() {
- return fInputs;
- }
-
- /**
- *
- * @return the parent trace
- */
- public CTFTrace getTrace() {
- return fTrace;
- }
-
- /**
- * Get all the event declarations in this stream.
- *
- * @return The event declarations for this stream
- * @since 2.0
- */
- public @NonNull List<@Nullable IEventDeclaration> getEventDeclarations() {
- return NonNullUtils.checkNotNull(Collections.unmodifiableList(fEvents));
- }
-
- /**
- * Get the event declaration for a given ID.
- *
- * @param eventId
- * The ID, can be {@link EventDeclaration#UNSET_EVENT_ID}, or any
- * positive value
- * @return The event declaration with the given ID for this stream, or
- * 'null' if there are no declaration with this ID
- * @throws IllegalArgumentException
- * If the passed ID is invalid
- */
- public @Nullable IEventDeclaration getEventDeclaration(int eventId) {
- int eventIndex = (eventId == IEventDeclaration.UNSET_EVENT_ID) ? 0 : eventId;
- if (eventIndex < 0) {
- /* Any negative value other than UNSET_EVENT_ID is invalid */
- throw new IllegalArgumentException("Event ID cannot be negative."); //$NON-NLS-1$
- }
- if (eventIndex >= fEvents.size()) {
- /* This ID could be valid, but there are no declarations with it */
- return null;
- }
- return fEvents.get(eventIndex);
- }
-
- // ------------------------------------------------------------------------
- // Operations
- // ------------------------------------------------------------------------
-
- /**
- * Adds an event to the event list.
- *
- * An event in a stream can omit its id if it is the only event in this
- * stream. An event for which no id has been specified has a null id. It is
- * thus not possible to add an event with the null key if the map is not
- * empty. It is also not possible to add an event to the map if the null key
- * is present in the map.
- *
- * @param event
- * The event to add
- * @throws ParseException
- * If there was a problem reading the event or adding it to the
- * stream
- */
- public void addEvent(IEventDeclaration event) throws ParseException {
- if (fEventUnsetId) {
- throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$
- }
- int id = ((EventDeclaration) event).id();
-
- /*
- * If there is an event without id (the null key), it must be the only
- * one
- */
- if (id == IEventDeclaration.UNSET_EVENT_ID) {
- if (!fEvents.isEmpty()) {
- throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$
- }
- fEventUnsetId = true;
- fEvents.add(event);
- } else {
- /* Check if an event with the same ID already exists */
- if (fEvents.size() > id && fEvents.get(id) != null) {
- throw new ParseException("Event id already exists"); //$NON-NLS-1$
- }
- ensureSize(fEvents, id);
- /* Put the event in the list */
- fEvents.set(id, event);
- }
- }
-
- /**
- * Add a list of event declarations to this stream. There must be no overlap
- * between the two lists of event declarations. This will merge the two
- * lists and preserve the indexes of both lists.
- *
- * @param events
- * list of the events to add
- * @throws CTFException
- * if the list already contains data
- */
- public void addEvents(Collection<IEventDeclaration> events) throws CTFException {
- if (fEventUnsetId) {
- throw new CTFException("Cannot add to a stream with an unidentified event"); //$NON-NLS-1$
- }
- if (fEvents.isEmpty()) {
- fEvents.addAll(events);
- return;
- }
- for (IEventDeclaration event : events) {
- if (event != null) {
- int index = event.getId().intValue();
- ensureSize(fEvents, index);
- if (fEvents.get(index) != null) {
- throw new CTFException("Both lists have an event defined at position " + index); //$NON-NLS-1$
- }
- fEvents.set(index, event);
- }
- }
- }
-
- private static void ensureSize(ArrayList<@Nullable ? extends Object> list, int index) {
- list.ensureCapacity(index);
- while (list.size() <= index) {
- list.add(null);
- }
- }
-
- /**
- * Add an input to this Stream
- *
- * @param input
- * The StreamInput to add.
- */
- public void addInput(CTFStreamInput input) {
- fInputs.add(input);
- }
-
- @Override
- public String toString() {
- return "Stream [id=" + fId + ", packetContextDecl=" + fPacketContextDecl //$NON-NLS-1$ //$NON-NLS-2$
- + ", eventHeaderDecl=" + fEventHeaderDecl //$NON-NLS-1$
- + ", eventContextDecl=" + fEventContextDecl + ", trace=" + fTrace //$NON-NLS-1$ //$NON-NLS-2$
- + ", events=" + fEvents + ", inputs=" + fInputs + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-}
/**
* The associated Stream
*/
- private final CTFStream fStream;
+ private final ICTFStream fStream;
/**
* Information on the file (used for debugging)
* The stream to which this StreamInput belongs to.
* @param file
* Information about the trace file (for debugging purposes).
+ * @since 2.0
*/
- public CTFStreamInput(CTFStream stream, File file) {
+ public CTFStreamInput(ICTFStream stream, File file) {
fStream = stream;
fFile = file;
String name = fFile.getName();
* Gets the stream the streamInput wrapper is wrapping
*
* @return the stream the streamInput wrapper is wrapping
+ * @since 2.0
*/
- public CTFStream getStream() {
+ public ICTFStream getStream() {
return fStream;
}
import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.internal.ctf.core.trace.Utils;
/**
/**
* Collection of streams contained in the trace.
*/
- private final Map<Long, CTFStream> fStreams = new HashMap<>();
+ private final Map<Long, ICTFStream> fStreams = new HashMap<>();
/**
* Collection of environment variables set by the tracer
}
/* Create their index */
- for (CTFStream stream : getStreams()) {
+ for (ICTFStream stream : getStreams()) {
Set<CTFStreamInput> inputs = stream.getStreamInputs();
for (CTFStreamInput s : inputs) {
addStream(s);
* @return The list of event declarations
*/
public Collection<IEventDeclaration> getEventDeclarations(Long streamId) {
- CTFStream stream = fStreams.get(streamId);
+ ICTFStream stream = fStreams.get(streamId);
if (stream == null) {
return null;
}
* @param id
* Long the id of the stream
* @return Stream the stream that we need
+ * @since 2.0
*/
- public CTFStream getStream(Long id) {
+ public ICTFStream getStream(Long id) {
if (id == null) {
return fStreams.get(0L);
}
*
* @return Iterable<Stream> an iterable over streams.
*/
- public Iterable<CTFStream> getStreams() {
+ public Iterable<ICTFStream> getStreams() {
return fStreams.values();
}
/*
* add the stream
*/
- CTFStream stream = s.getStream();
+ ICTFStream stream = s.getStream();
fStreams.put(stream.getId(), stream);
/*
* @throws CTFException
* if there is a file error
*/
- private CTFStream openStreamInput(File streamFile) throws CTFException {
+ private ICTFStream openStreamInput(File streamFile) throws CTFException {
ByteBuffer byteBuffer;
BitBuffer streamBitBuffer;
- CTFStream stream;
+ ICTFStream stream;
if (!streamFile.canRead()) {
throw new CTFException("Unreadable file : " //$NON-NLS-1$
throw new CTFException("Unexpected end of stream"); //$NON-NLS-1$
}
+ if (!(stream instanceof CTFStream)) {
+ throw new CTFException("Stream is not a CTFStream, but rather a " + stream.getClass().getCanonicalName()); //$NON-NLS-1$
+ }
+ CTFStream ctfStream = (CTFStream) stream;
/*
* Create the stream input and add a reference to the streamInput in the
* stream.
*/
- stream.addInput(new CTFStreamInput(stream, streamFile));
-
- return stream;
+ ctfStream.addInput(new CTFStreamInput(ctfStream, streamFile));
+ return ctfStream;
}
private void validateUUID(StructDefinition packetHeaderDef) throws CTFException {
* A stream object.
* @throws ParseException
* If there was some problem reading the metadata
+ * @since 2.0
*/
- public void addStream(CTFStream stream) throws ParseException {
+ public void addStream(ICTFStream stream) throws ParseException {
/*
* If there is already a stream without id (the null key), it must be
* the only one
/*
* If a stream with the same ID already exists, it is not valid.
*/
- CTFStream existingStream = fStreams.get(stream.getId());
+ ICTFStream existingStream = fStreams.get(stream.getId());
if (existingStream != null) {
throw new ParseException("Stream id already exists"); //$NON-NLS-1$
}
*/
public long getCurrentStartTime() {
long currentStart = Long.MAX_VALUE;
- for (CTFStream stream : fStreams.values()) {
+ for (ICTFStream stream : fStreams.values()) {
for (CTFStreamInput si : stream.getStreamInputs()) {
currentStart = Math.min(currentStart, si.getIndex().getElement(0).getTimestampBegin());
}
*/
public long getCurrentEndTime() {
long currentEnd = Long.MIN_VALUE;
- for (CTFStream stream : fStreams.values()) {
+ for (ICTFStream stream : fStreams.values()) {
for (CTFStreamInput si : stream.getStreamInputs()) {
currentEnd = Math.max(currentEnd, si.getTimestampEnd());
}
if (file == null) {
throw new CTFException("cannot create a stream with no file"); //$NON-NLS-1$
}
- CTFStream stream = fStreams.get(id);
+ ICTFStream stream = fStreams.get(id);
if (stream == null) {
stream = new CTFStream(this);
fStreams.put(id, stream);
}
- stream.addInput(new CTFStreamInput(stream, file));
+ if (stream instanceof CTFStream) {
+ CTFStream ctfStream = (CTFStream) stream;
+ ctfStream.addInput(new CTFStreamInput(stream, file));
+ } else {
+ throw new CTFException("Stream does not support adding input"); //$NON-NLS-1$
+ }
}
/**
/*
* For each stream.
*/
- for (CTFStream stream : fTrace.getStreams()) {
+ for (ICTFStream stream : fTrace.getStreams()) {
Set<CTFStreamInput> streamInputs = stream.getStreamInputs();
/*
*/
public void update() throws CTFException {
Set<CTFStreamInputReader> readers = new HashSet<>();
- for (CTFStream stream : fTrace.getStreams()) {
+ for (ICTFStream stream : fTrace.getStreams()) {
Set<CTFStreamInput> streamInputs = stream.getStreamInputs();
for (CTFStreamInput streamInput : streamInputs) {
/*
}
// Copy packets
- for (CTFStream stream : trace.getStreams()) {
+ for (ICTFStream stream : trace.getStreams()) {
Set<CTFStreamInput> inputs = stream.getStreamInputs();
for (CTFStreamInput s : inputs) {
CTFStreamOutputWriter streamOutputwriter = new CTFStreamOutputWriter(checkNotNull(s), out);
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
+ *
+ * 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
+ *
+ * Contributors: Matthew Khouzam - Initial API and implementation
+ * Contributors: Simon Marchi - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.ctf.core.trace;
+
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+
+/**
+ * An _event stream_ can be divided into contiguous event packets of variable
+ * size. An event packet can contain a certain amount of padding at the end. The
+ * stream header is repeated at the beginning of each event packet. The
+ * rationale for the event stream design choices is explained in
+ * <a href="http://diamon.org/ctf/#specB" >Stream header rationale<a/>.
+ * <p>
+ *
+ * The event stream header will therefore be referred to as the _event packet
+ * header_ throughout the rest of this document.
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - Javadoc
+ * @since 2.0
+ */
+public interface ICTFStream {
+
+ /**
+ * Gets the id of a stream
+ *
+ * @return id the id of a stream
+ * @since 1.0
+ */
+ long getId();
+
+ /**
+ * Is the id of a stream set
+ *
+ * @return If the ID is set or not
+ */
+ boolean isIdSet();
+
+ /**
+ *
+ * @return is the event header set (timestamp and stuff) (see Ctf Spec)
+ */
+ boolean isEventHeaderSet();
+
+ /**
+ *
+ * @return is the event context set (pid and stuff) (see Ctf Spec)
+ */
+ boolean isEventContextSet();
+
+ /**
+ *
+ * @return Is the packet context set (see Ctf Spec)
+ */
+ boolean isPacketContextSet();
+
+ /**
+ * Gets the event header declaration
+ *
+ * @return the event header declaration in declaration form
+ */
+ IDeclaration getEventHeaderDeclaration();
+
+ /**
+ *
+ * @return the event context declaration in structdeclaration form
+ */
+ StructDeclaration getEventContextDecl();
+
+ /**
+ *
+ * @return the packet context declaration in structdeclaration form
+ */
+ StructDeclaration getPacketContextDecl();
+
+ /**
+ *
+ * @return the set of all stream inputs for this stream
+ */
+ Set<CTFStreamInput> getStreamInputs();
+
+ /**
+ *
+ * @return the parent trace
+ */
+ CTFTrace getTrace();
+
+ /**
+ * Get all the event declarations in this stream.
+ *
+ * @return The event declarations for this stream
+ * @since 2.0
+ */
+ @NonNull
+ List<@Nullable IEventDeclaration> getEventDeclarations();
+
+ /**
+ * Get the event declaration for a given ID.
+ *
+ * @param eventId
+ * The ID, can be {@link EventDeclaration#UNSET_EVENT_ID}, or any
+ * positive value
+ * @return The event declaration with the given ID for this stream, or
+ * 'null' if there are no declaration with this ID
+ * @throws IllegalArgumentException
+ * If the passed ID is invalid
+ */
+ @Nullable
+ IEventDeclaration getEventDeclaration(int eventId);
+
+}
\ No newline at end of file
import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
import org.eclipse.tracecompass.ctf.core.trace.CTFIOException;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInputReader;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
import org.eclipse.tracecompass.ctf.core.trace.ICTFPacketDescriptor;
import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
/**
* Representation of one type of event. A bit like "int" or "long" but for trace
import org.eclipse.tracecompass.ctf.core.event.types.StringDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
import org.eclipse.tracecompass.ctf.parser.CTFParser;
import org.eclipse.tracecompass.internal.ctf.core.Activator;
import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
import org.eclipse.tracecompass.internal.ctf.core.event.types.StructDeclarationFlattener;
import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderCompactDeclaration;
import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderLargeDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
import com.google.common.collect.Iterables;
EnumDeclaration newEnum = new EnumDeclaration(IntegerDeclaration.createDeclaration(containerType.getLength(), containerType.isSigned(),
containerType.getBase(), byteOrder, containerType.getEncoding(),
containerType.getClock(), containerType.getAlignment()));
- for( Entry<String, Pair> entry : decl.getEnumTable().entrySet()){
- newEnum.add(entry.getValue().getFirst(), entry.getValue().getSecond(), entry.getKey());
+ for (Entry<String, Pair> entry : decl.getEnumTable().entrySet()) {
+ newEnum.add(entry.getValue().getFirst(), entry.getValue().getSecond(), entry.getKey());
}
parentScope.replaceType(name, newEnum);
* could be possible to just get the only existing stream, whatever
* is its id.
*/
- CTFStream stream = fTrace.getStream(null);
+ ICTFStream iStream = fTrace.getStream(null);
+ if (iStream instanceof CTFStream) {
- if (stream != null) {
- event.setStream(stream);
+ CTFStream ctfStream = (CTFStream) iStream;
+ event.setStream(ctfStream);
} else {
throw new ParseException("Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
}
event.getStream().addEvent(event);
popScope();
+
}
private void parseEventDeclaration(CommonTree eventDecl,
long streamId = getStreamID(rightNode);
- CTFStream stream = fTrace.getStream(streamId);
+ ICTFStream iStream = fTrace.getStream(streamId);
- if (stream == null) {
+ if (iStream instanceof CTFStream) {
+ CTFStream stream = (CTFStream) iStream;
+ event.setStream(stream);
+ } else {
throw new ParseException("Stream " + streamId + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
}
- event.setStream(stream);
} else if (left.equals(MetadataStrings.CONTEXT)) {
if (event.contextIsSet()) {
throw new ParseException("context already defined"); //$NON-NLS-1$
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
+ *
+ * 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
+ *
+ * Contributors: Matthew Khouzam - Initial API and implementation
+ * Contributors: Simon Marchi - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.trace;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.ctf.core.CTFException;
+import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
+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.ICTFStream;
+import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+
+/**
+ * <b><u>Stream</u></b>
+ * <p>
+ * Represents a stream in a trace.
+ */
+public class CTFStream implements ICTFStream {
+
+ // ------------------------------------------------------------------------
+ // Attributes
+ // ------------------------------------------------------------------------
+
+ /**
+ * The numerical ID of the stream
+ */
+ private long fId = 0;
+
+ /**
+ * Declarations of the stream-specific structures
+ */
+ private StructDeclaration fPacketContextDecl = null;
+ private IDeclaration fEventHeaderDecl = null;
+ private StructDeclaration fEventContextDecl = null;
+
+ /**
+ * The trace to which the stream belongs
+ */
+ private CTFTrace fTrace = null;
+
+ /**
+ * Maps event ids to events
+ */
+ private final ArrayList<@Nullable IEventDeclaration> fEvents = new ArrayList<>();
+
+ private boolean fEventUnsetId = false;
+ private boolean fStreamIdSet = false;
+
+ /**
+ * The inputs associated to this stream
+ */
+ private final Set<CTFStreamInput> fInputs = new HashSet<>();
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a Stream that belongs to a Trace
+ *
+ * @param trace
+ * The trace to which belongs this stream.
+ */
+ public CTFStream(CTFTrace trace) {
+ fTrace = trace;
+ }
+
+ // ------------------------------------------------------------------------
+ // Getters/Setters/Predicates
+ // ------------------------------------------------------------------------
+
+ /**
+ * Sets the id of a stream
+ *
+ * @param id
+ * the id of a stream
+ */
+ public void setId(long id) {
+ fId = id;
+ fStreamIdSet = true;
+ }
+
+ @Override
+ public long getId() {
+ return fId;
+ }
+
+ @Override
+ public boolean isIdSet() {
+ return fStreamIdSet;
+ }
+
+ @Override
+ public boolean isEventHeaderSet() {
+ return fEventHeaderDecl != null;
+ }
+
+ @Override
+ public boolean isEventContextSet() {
+ return fEventContextDecl != null;
+ }
+
+ @Override
+ public boolean isPacketContextSet() {
+ return fPacketContextDecl != null;
+ }
+
+ /**
+ * Sets the event header
+ *
+ * @param eventHeader
+ * the current event header for all events in this stream
+ */
+ public void setEventHeader(StructDeclaration eventHeader) {
+ fEventHeaderDecl = eventHeader;
+ }
+
+ /**
+ * Sets the event header, this typically has the id and the timestamp
+ *
+ * @param eventHeader
+ * the current event header for all events in this stream
+ */
+ public void setEventHeader(IEventHeaderDeclaration eventHeader) {
+ fEventHeaderDecl = eventHeader;
+ }
+
+ /**
+ *
+ * @param eventContext
+ * the context for all events in this stream
+ */
+ public void setEventContext(StructDeclaration eventContext) {
+ fEventContextDecl = eventContext;
+ }
+
+ /**
+ *
+ * @param packetContext
+ * the packet context for all packets in this stream
+ */
+ public void setPacketContext(StructDeclaration packetContext) {
+ fPacketContextDecl = packetContext;
+ }
+
+ @Override
+ public IDeclaration getEventHeaderDeclaration() {
+ return fEventHeaderDecl;
+ }
+
+ @Override
+ public StructDeclaration getEventContextDecl() {
+ return fEventContextDecl;
+ }
+
+ @Override
+ public StructDeclaration getPacketContextDecl() {
+ return fPacketContextDecl;
+ }
+
+ @Override
+ public Set<CTFStreamInput> getStreamInputs() {
+ return fInputs;
+ }
+
+ @Override
+ public CTFTrace getTrace() {
+ return fTrace;
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ public List<@Nullable IEventDeclaration> getEventDeclarations() {
+ return NonNullUtils.checkNotNull(Collections.unmodifiableList(fEvents));
+ }
+
+ @Override
+ public IEventDeclaration getEventDeclaration(int eventId) {
+ int eventIndex = (eventId == IEventDeclaration.UNSET_EVENT_ID) ? 0 : eventId;
+ if (eventIndex < 0) {
+ /* Any negative value other than UNSET_EVENT_ID is invalid */
+ throw new IllegalArgumentException("Event ID cannot be negative."); //$NON-NLS-1$
+ }
+ if (eventIndex >= fEvents.size()) {
+ /* This ID could be valid, but there are no declarations with it */
+ return null;
+ }
+ return fEvents.get(eventIndex);
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ /**
+ * Adds an event to the event list.
+ *
+ * An event in a stream can omit its id if it is the only event in this
+ * stream. An event for which no id has been specified has a null id. It is
+ * thus not possible to add an event with the null key if the map is not
+ * empty. It is also not possible to add an event to the map if the null key
+ * is present in the map.
+ *
+ * @param event
+ * The event to add
+ * @throws ParseException
+ * If there was a problem reading the event or adding it to the
+ * stream
+ * @since 2.0
+ */
+ public void addEvent(IEventDeclaration event) throws ParseException {
+ if (fEventUnsetId) {
+ throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$
+ }
+ int id = ((EventDeclaration) event).id();
+
+ /*
+ * If there is an event without id (the null key), it must be the only
+ * one
+ */
+ if (id == IEventDeclaration.UNSET_EVENT_ID) {
+ if (!fEvents.isEmpty()) {
+ throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$
+ }
+ fEventUnsetId = true;
+ fEvents.add(event);
+ } else {
+ /* Check if an event with the same ID already exists */
+ if (fEvents.size() > id && fEvents.get(id) != null) {
+ throw new ParseException("Event id already exists"); //$NON-NLS-1$
+ }
+ ensureSize(fEvents, id);
+ /* Put the event in the list */
+ fEvents.set(id, event);
+ }
+ }
+
+ /**
+ * Add a list of event declarations to this stream. There must be no overlap
+ * between the two lists of event declarations. This will merge the two
+ * lists and preserve the indexes of both lists.
+ *
+ * @param events
+ * list of the events to add
+ * @throws CTFException
+ * if the list already contains data
+ */
+ public void addEvents(Collection<IEventDeclaration> events) throws CTFException {
+ if (fEventUnsetId) {
+ throw new CTFException("Cannot add to a stream with an unidentified event"); //$NON-NLS-1$
+ }
+ if (fEvents.isEmpty()) {
+ fEvents.addAll(events);
+ return;
+ }
+ for (IEventDeclaration event : events) {
+ if (event != null) {
+ int index = event.getId().intValue();
+ ensureSize(fEvents, index);
+ if (fEvents.get(index) != null) {
+ throw new CTFException("Both lists have an event defined at position " + index); //$NON-NLS-1$
+ }
+ fEvents.set(index, event);
+ }
+ }
+ }
+
+ private static void ensureSize(ArrayList<@Nullable ? extends Object> list, int index) {
+ list.ensureCapacity(index);
+ while (list.size() <= index) {
+ list.add(null);
+ }
+ }
+
+ /**
+ * Add an input to this Stream
+ *
+ * @param input
+ * The StreamInput to add.
+ */
+ public void addInput(CTFStreamInput input) {
+ fInputs.add(input);
+ }
+
+ @Override
+ public String toString() {
+ return "Stream [id=" + fId + ", packetContextDecl=" + fPacketContextDecl //$NON-NLS-1$ //$NON-NLS-2$
+ + ", eventHeaderDecl=" + fEventHeaderDecl //$NON-NLS-1$
+ + ", eventContextDecl=" + fEventContextDecl + ", trace=" + fTrace //$NON-NLS-1$ //$NON-NLS-2$
+ + ", events=" + fEvents + ", inputs=" + fInputs + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+}