/*******************************************************************************
- * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
+ * Copyright (c) 2011-2013 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
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel.MapMode;
import java.util.Collection;
-import java.util.HashMap;
-import org.eclipse.linuxtools.ctf.core.event.EventDeclaration;
+import org.eclipse.linuxtools.ctf.core.CTFStrings;
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
+import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
+import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
import org.eclipse.linuxtools.ctf.core.event.types.Definition;
import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.VariantDefinition;
-import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
-import org.eclipse.linuxtools.internal.ctf.core.trace.Stream;
+import org.eclipse.linuxtools.internal.ctf.core.event.EventDeclaration;
import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
/**
public class StreamInputPacketReader implements IDefinitionScope {
// ------------------------------------------------------------------------
- // Constants
+ // Attributes
// ------------------------------------------------------------------------
- /**
- * Reference to the index entry of the current packet.
- */
- private StreamInputPacketIndexEntry currentPacket = null;
-
- /**
- * BitBuffer used to read the trace file.
- */
- private final BitBuffer bitBuffer = new BitBuffer();
+ /** BitBuffer used to read the trace file. */
+ private final BitBuffer bitBuffer;
- /**
- * StreamInputReader that uses this StreamInputPacketReader.
- */
+ /** StreamInputReader that uses this StreamInputPacketReader. */
private final StreamInputReader streamInputReader;
- /**
- * Last timestamp recorded.
- *
- * Needed to calculate the complete timestamp values for the events with
- * compact headers.
- */
- private long lastTimestamp = 0;
+ /** Trace packet header. */
+ private final StructDefinition tracePacketHeaderDef;
- /**
- * Trace packet header.
- */
- private StructDefinition tracePacketHeaderDef = null;
+ /** Stream packet context definition. */
+ private final StructDefinition streamPacketContextDef;
- /**
- * Stream packet context definition.
- */
- private StructDefinition streamPacketContextDef = null;
+ /** Stream event header definition. */
+ private final StructDefinition streamEventHeaderDef;
- /**
- * Stream event header definition.
- */
- private StructDefinition streamEventHeaderDef = null;
+ /** Stream event context definition. */
+ private final StructDefinition streamEventContextDef;
- /**
- * Stream event context definition.
- */
- private StructDefinition streamEventContextDef = null;
+ /** Reference to the index entry of the current packet. */
+ private StreamInputPacketIndexEntry currentPacket = null;
/**
- * Maps event ID to event definitions.
+ * Last timestamp recorded.
+ *
+ * Needed to calculate the complete timestamp values for the events with
+ * compact headers.
*/
- private final HashMap<Long, EventDefinition> events;
+ private long lastTimestamp = 0;
- /**
- * CPU id of current packet.
- */
+ /** CPU id of current packet. */
private int currentCpu = 0;
- /**
- * number of lost events in this packet
- */
- private int lostSoFar;
-
private int lostEventsInThisPacket;
+ private long lostEventsDuration;
+
+ private boolean hasLost = false;
+
// ------------------------------------------------------------------------
- // Attributes
+ // Constructors
// ------------------------------------------------------------------------
/**
public StreamInputPacketReader(StreamInputReader streamInputReader) {
this.streamInputReader = streamInputReader;
- /*
- * Set the BitBuffer's byte order.
- */
- getBitBuffer().setByteOrder(streamInputReader.getByteOrder());
+ /* Set the BitBuffer's byte order. */
+ bitBuffer = new BitBuffer();
+ bitBuffer.setByteOrder(streamInputReader.getByteOrder());
- events = streamInputReader.getStreamInput().getStream().getTrace()
- .getEventDefs(streamInputReader.getStreamInput());
- /*
- * Create definitions needed to read the events.
- */
- createDefinitions();
+ /* Create trace packet header definition. */
+ final Stream currentStream = streamInputReader.getStreamInput().getStream();
+ StructDeclaration tracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
+ if (tracePacketHeaderDecl != null) {
+ tracePacketHeaderDef = tracePacketHeaderDecl.createDefinition(this, "trace.packet.header"); //$NON-NLS-1$
+ } else {
+ tracePacketHeaderDef = null;
+ }
- lostSoFar = 0;
+ /* Create stream packet context definition. */
+ StructDeclaration streamPacketContextDecl = currentStream.getPacketContextDecl();
+ if (streamPacketContextDecl != null) {
+ streamPacketContextDef = streamPacketContextDecl.createDefinition(this, "stream.packet.context"); //$NON-NLS-1$
+ } else {
+ streamPacketContextDef = null;
+ }
+
+ /* Create stream event header definition. */
+ StructDeclaration streamEventHeaderDecl = currentStream.getEventHeaderDecl();
+ if (streamEventHeaderDecl != null) {
+ streamEventHeaderDef = streamEventHeaderDecl.createDefinition(this, "stream.event.header"); //$NON-NLS-1$
+ } else {
+ streamEventHeaderDef = null;
+ }
+
+ /* Create stream event context definition. */
+ StructDeclaration streamEventContextDecl = currentStream.getEventContextDecl();
+ if (streamEventContextDecl != null) {
+ streamEventContextDef = streamEventContextDecl.createDefinition(this, "stream.event.context"); //$NON-NLS-1$
+ } else {
+ streamEventContextDef = null;
+ }
+
+ /* Create event definitions */
+ Collection<IEventDeclaration> eventDecls = streamInputReader.getStreamInput().getStream().getEvents().values();
+
+ for (IEventDeclaration event : eventDecls) {
+ if (!streamInputReader.getEventDefinitions().containsKey(event.getId())) {
+ EventDefinition eventDef = event.createDefinition(streamInputReader);
+ streamInputReader.addEventDefinition(event.getId(), eventDef);
+ }
+ }
}
- // ------------------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------------------
+ /**
+ * Dispose the StreamInputPacketReader
+ *
+ * @since 2.0
+ */
+ public void dispose() {
+ bitBuffer.setByteBuffer(null);
+ }
// ------------------------------------------------------------------------
// Getters/Setters/Predicates
*
* @return the current packet
*/
- public StreamInputPacketIndexEntry getCurrentPacket() {
+ StreamInputPacketIndexEntry getCurrentPacket() {
return this.currentPacket;
}
return this.streamPacketContextDef;
}
+ /**
+ * Gets the stream's event context definition.
+ *
+ * @return The streamEventContext definition
+ */
+ public StructDefinition getStreamEventContextDef() {
+ return streamEventContextDef;
+ }
+
/**
* Gets the CPU (core) number
*
// Operations
// ------------------------------------------------------------------------
- /**
- * Creates definitions needed to read events (stream-defined and
- * event-defined).
- */
- private void createDefinitions() {
- /*
- * Create trace packet header definition.
- */
- final Stream currentStream = getStreamInputReader().getStreamInput()
- .getStream();
- StructDeclaration tracePacketHeaderDecl = currentStream.getTrace()
- .getPacketHeader();
- if (tracePacketHeaderDecl != null) {
- setTracePacketHeaderDef(tracePacketHeaderDecl.createDefinition(
- this, "trace.packet.header")); //$NON-NLS-1$
- }
-
- /*
- * Create stream packet context definition.
- */
- StructDeclaration streamPacketContextDecl = currentStream
- .getPacketContextDecl();
- if (streamPacketContextDecl != null) {
- setStreamPacketContextDef(streamPacketContextDecl.createDefinition(
- this, "stream.packet.context")); //$NON-NLS-1$
- }
-
- /*
- * Create stream event header definition.
- */
- StructDeclaration streamEventHeaderDecl = currentStream
- .getEventHeaderDecl();
- if (streamEventHeaderDecl != null) {
- setStreamEventHeaderDef(streamEventHeaderDecl.createDefinition(
- this, "stream.event.header")); //$NON-NLS-1$
- }
-
- /*
- * Create stream event context definition.
- */
- StructDeclaration streamEventContextDecl = currentStream
- .getEventContextDecl();
- if (streamEventContextDecl != null) {
- setStreamEventContextDef(streamEventContextDecl.createDefinition(
- this, "stream.event.context")); //$NON-NLS-1$
- }
-
- createEventDefinitions();
- }
-
- /**
- * Creates definitions needed to read the event. (event-defined).
- */
- private void createEventDefinitions() {
- Collection<EventDeclaration> eventDecls = getStreamInputReader()
- .getStreamInput().getStream().getEvents().values();
-
- /*
- * Create definitions for each event.
- */
- for (EventDeclaration event : eventDecls) {
- if (!events.containsKey(event.getId())) {
- EventDefinition eventDef = event
- .createDefinition(getStreamInputReader());
- events.put(event.getId(), eventDef);
- }
- }
- }
-
/**
* Changes the current packet to the given one.
*
* @param currentPacket
* The index entry of the packet to switch to.
+ * @throws CTFReaderException
+ * If we get an error reading the packet
*/
- public void setCurrentPacket(StreamInputPacketIndexEntry currentPacket) {
+ void setCurrentPacket(StreamInputPacketIndexEntry currentPacket) throws CTFReaderException {
+ StreamInputPacketIndexEntry prevPacket = null;
this.currentPacket = currentPacket;
if (this.currentPacket != null) {
*/
MappedByteBuffer bb = null;
try {
- bb = getStreamInputReader()
- .getStreamInput()
- .getFileChannel()
+ bb = streamInputReader.getStreamInput().getFileChannel()
.map(MapMode.READ_ONLY,
this.currentPacket.getOffsetBytes(),
(this.currentPacket.getPacketSizeBits() + 7) / 8);
} catch (IOException e) {
- /*
- * The streamInputReader object is already allocated, so this
- * shouldn't fail bar some very bad kernel or RAM errors...
- */
- e.printStackTrace();
+ throw new CTFReaderException(e.getMessage(), e);
}
- getBitBuffer().setByteBuffer(bb);
+ bitBuffer.setByteBuffer(bb);
/*
* Read trace packet header.
*/
- if (getTracePacketHeaderDef() != null) {
- getTracePacketHeaderDef().read(getBitBuffer());
+ if (tracePacketHeaderDef != null) {
+ tracePacketHeaderDef.read(bitBuffer);
}
/*
* Read stream packet context.
*/
if (getStreamPacketContextDef() != null) {
- getStreamPacketContextDef().read(getBitBuffer());
+ getStreamPacketContextDef().read(bitBuffer);
/* Read CPU ID */
if (this.getCurrentPacket().getTarget() != null) {
/* Read number of lost events */
lostEventsInThisPacket = (int) this.getCurrentPacket().getLostEvents();
- lostSoFar = 0;
-
+ if (lostEventsInThisPacket != 0) {
+ hasLost = true;
+ /*
+ * Compute the duration of the lost event time range. If the
+ * current packet is the first packet, duration will be set
+ * to 1.
+ */
+ long lostEventsStartTime;
+ int index = this.streamInputReader.getStreamInput().getIndex().getEntries().indexOf(currentPacket);
+ if (index == 0) {
+ lostEventsStartTime = currentPacket.getTimestampBegin() + 1;
+ } else {
+ prevPacket = this.streamInputReader.getStreamInput().getIndex().getEntries().get(index - 1);
+ lostEventsStartTime = prevPacket.getTimestampEnd();
+ }
+ lostEventsDuration = Math.abs(lostEventsStartTime - currentPacket.getTimestampBegin());
+ }
}
/*
*/
lastTimestamp = currentPacket.getTimestampBegin();
} else {
- getBitBuffer().setByteBuffer(null);
+ bitBuffer.setByteBuffer(null);
lastTimestamp = 0;
}
*/
public boolean hasMoreEvents() {
if (currentPacket != null) {
- return getBitBuffer().position() < currentPacket
- .getContentSizeBits();
+ return hasLost || (bitBuffer.position() < currentPacket.getContentSizeBits());
}
return false;
}
* If there was a problem reading the trace
*/
public EventDefinition readNextEvent() throws CTFReaderException {
- /* WARNING: This is still LTTng-specific. */
- Long eventID = null;
+ /* Default values for those fields */
+ long eventID = EventDeclaration.UNSET_EVENT_ID;
long timestamp = 0;
-
- if (lostEventsInThisPacket > lostSoFar) {
- EventDefinition eventDef = EventDeclaration
- .getLostEventDeclaration().createDefinition(
- streamInputReader);
+ if (hasLost) {
+ hasLost = false;
+ EventDefinition eventDef = EventDeclaration.getLostEventDeclaration().createDefinition(streamInputReader);
+ ((IntegerDefinition) eventDef.getFields().getDefinitions().get(CTFStrings.LOST_EVENTS_FIELD)).setValue(lostEventsInThisPacket);
+ ((IntegerDefinition) eventDef.getFields().getDefinitions().get(CTFStrings.LOST_EVENTS_DURATION)).setValue(lostEventsDuration);
eventDef.setTimestamp(this.lastTimestamp);
- ++lostSoFar;
return eventDef;
}
- StructDefinition sehd = getStreamEventHeaderDef(); // acronym for a long
- // variable name
- BitBuffer currentBitBuffer = getBitBuffer();
- /*
- * Read the stream event header.
- */
-
+ final StructDefinition sehd = streamEventHeaderDef;
+ final BitBuffer currentBitBuffer = bitBuffer;
+ final long posStart = currentBitBuffer.position();
+ /* Read the stream event header. */
if (sehd != null) {
sehd.read(currentBitBuffer);
+ /* Check for the event id. */
+ Definition idDef = sehd.lookupDefinition("id"); //$NON-NLS-1$
+ if (idDef instanceof SimpleDatatypeDefinition) {
+ eventID = ((SimpleDatatypeDefinition) idDef).getIntegerValue();
+ } else if (idDef != null) {
+ throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
+ }
+
/*
- * Check for an event id.
+ * Get the timestamp from the event header (may be overridden later
+ * on)
*/
- SimpleDatatypeDefinition idDef = (SimpleDatatypeDefinition) sehd
- .lookupDefinition("id"); //$NON-NLS-1$
IntegerDefinition timestampDef = sehd.lookupInteger("timestamp"); //$NON-NLS-1$
- eventID = idDef.getIntegerValue();
+ if (timestampDef != null) {
+ timestamp = calculateTimestamp(timestampDef);
+ } // else timestamp remains 0
- /*
- * Check for the variant v.
- */
- VariantDefinition variantDef = (VariantDefinition) sehd
- .lookupDefinition("v"); //$NON-NLS-1$
- if (variantDef != null) {
+ /* Check for the variant v. */
+ Definition variantDef = sehd.lookupDefinition("v"); //$NON-NLS-1$
+ if (variantDef instanceof VariantDefinition) {
- /*
- * Get the variant current field
- */
- StructDefinition variantCurrentField = (StructDefinition) variantDef
- .getCurrentField();
+ /* Get the variant current field */
+ StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
/*
* Try to get the id field in the current field of the variant.
* If it is present, it overrides the previously read event id.
*/
- IntegerDefinition idIntegerDef = (IntegerDefinition) variantCurrentField
- .lookupDefinition("id"); //$NON-NLS-1$
- if (idIntegerDef != null) {
- eventID = idIntegerDef.getValue();
+ Definition idIntegerDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
+ if (idIntegerDef instanceof IntegerDefinition) {
+ eventID = ((IntegerDefinition) idIntegerDef).getValue();
}
+
/*
- * Get the timestamp.
+ * Get the timestamp. This would overwrite any previous
+ * timestamp definition
*/
- timestampDef = (IntegerDefinition) variantCurrentField
- .lookupDefinition("timestamp"); //$NON-NLS-1$
-
+ Definition def = variantCurrentField.lookupDefinition("timestamp"); //$NON-NLS-1$
+ if (def instanceof IntegerDefinition) {
+ timestamp = calculateTimestamp((IntegerDefinition) def);
+ }
}
-
- /*
- * Calculate the event timestamp.
- */
- timestamp = calculateTimestamp(timestampDef);
}
- /*
- * Read the stream event context.
- */
- if (getStreamEventContextDef() != null) {
- getStreamEventContextDef().read(currentBitBuffer);
+ /* Read the stream event context. */
+ if (streamEventContextDef != null) {
+ streamEventContextDef.read(currentBitBuffer);
}
- /*
- * Get the right event definition using the event id.
- */
- EventDefinition eventDef = events.get(eventID);
+ /* Get the right event definition using the event id. */
+ EventDefinition eventDef = streamInputReader.getEventDefinitions().get(eventID);
if (eventDef == null) {
throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
}
- /*
- * Read the event context.
- */
- if (eventDef.getContext() != null) {
- eventDef.getContext().read(currentBitBuffer);
+ /* Read the event context. */
+ if (eventDef.getEventContext() != null) {
+ eventDef.getEventContext().read(currentBitBuffer);
}
- /*
- * Read the event fields.
- */
+ /* Read the event fields. */
if (eventDef.getFields() != null) {
eventDef.getFields().read(currentBitBuffer);
}
*/
eventDef.setTimestamp(timestamp);
+ if (posStart == currentBitBuffer.position()) {
+ throw new CTFReaderException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$
+ }
+
return eventDef;
}
@Override
public Definition lookupDefinition(String lookupPath) {
- // TODO Auto-generated method stub
return null;
}
-
- /**
- * Gets the stream event context definition (see CTF specs)
- *
- * @return the definition of the stream event context (the form not the
- * content)
- */
- public StructDefinition getStreamEventContextDef() {
- return this.streamEventContextDef;
- }
-
- /**
- * Sets the stream event context definition
- *
- * @param streamEventContextDef
- * The stream event context definition
- */
- public void setStreamEventContextDef(StructDefinition streamEventContextDef) {
- this.streamEventContextDef = streamEventContextDef;
- }
-
- /**
- * Gets the stream event header definition
- *
- * @return the stream event header definition
- */
- public StructDefinition getStreamEventHeaderDef() {
- return this.streamEventHeaderDef;
- }
-
- /**
- * Sets the stream event header definition
- *
- * @param streamEventHeaderDef
- * the stream event header definition
- */
- public void setStreamEventHeaderDef(StructDefinition streamEventHeaderDef) {
- this.streamEventHeaderDef = streamEventHeaderDef;
- }
-
- /**
- * Sets the stream packet context definition
- *
- * @param streamPacketContextDef
- * the stream packet context definition
- */
- public void setStreamPacketContextDef(
- StructDefinition streamPacketContextDef) {
- this.streamPacketContextDef = streamPacketContextDef;
- }
-
- /**
- * Gets the trace packet header definition
- *
- * @return the trace packet header definition
- */
- public StructDefinition getTracePacketHeaderDef() {
- return this.tracePacketHeaderDef;
- }
-
- /**
- * Sets the trace packet header definition
- *
- * @param tracePacketHeaderDef
- * the trace packet header definition
- */
- public void setTracePacketHeaderDef(StructDefinition tracePacketHeaderDef) {
- this.tracePacketHeaderDef = tracePacketHeaderDef;
- }
-
- /**
- * @return the parent stream input reader
- */
- public StreamInputReader getStreamInputReader() {
- return this.streamInputReader;
- }
-
- /**
- *
- * @return THe bit buffer that reads the file.
- */
- public BitBuffer getBitBuffer() {
- return bitBuffer;
- }
}