package org.eclipse.linuxtools.ctf.core.trace;
-import java.util.ListIterator;
+import java.nio.ByteOrder;
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
+import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInput;
+import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
/**
* <b><u>StreamInputReader</u></b>
/**
* Iterator on the packet index
*/
- private ListIterator<StreamInputPacketIndexEntry> packetIndexIt;
-
+ private int packetIndex;
/**
* Reference to the current event of this trace file (iow, the last on that
private int name;
+ private CTFTraceReader parent;
+
+ private final long prevIndex;
+
// ------------------------------------------------------------------------
// Constructors
// ------------------------------------------------------------------------
public StreamInputReader(StreamInput streamInput) {
this.streamInput = streamInput;
this.packetReader = new StreamInputPacketReader(this);
-
/*
* Get the iterator on the packet index.
*/
- this.packetIndexIt = streamInput.getIndex().listIterator();
+ this.packetIndex = 0;
+ this.prevIndex = 0;
/*
* Make first packet the current one.
*/
// Getters/Setters/Predicates
// ------------------------------------------------------------------------
+ /**
+ * Gets the current event in this stream
+ *
+ * @return the current event in the stream, null if the stream is
+ * finished/empty/malformed
+ */
public EventDefinition getCurrentEvent() {
return this.currentEvent;
}
+ /**
+ * gets the current packet context
+ *
+ * @return the current packet context (size, lost events and such)
+ */
public StructDefinition getCurrentPacketContext() {
return this.packetReader.getStreamPacketContextDef();
}
- public StreamInput getStreamInput() {
- return this.streamInput;
+ /**
+ * Gets the byte order for a trace
+ *
+ * @return the trace byte order
+ */
+ public ByteOrder getByteOrder() {
+ return streamInput.getStream().getTrace().getByteOrder();
}
+ /**
+ * Gets the name of the stream (it's an id and a number)
+ *
+ * @return gets the stream name (it's a number)
+ */
public int getName() {
return this.name;
}
+ /**
+ * Sets the name of the stream
+ *
+ * @param name
+ * the name of the stream, (it's a number)
+ */
public void setName(int name) {
this.name = name;
}
+ /**
+ * Gets the CPU of a stream. It's the same as the one in /proc or running
+ * the asm CPUID instruction
+ *
+ * @return The CPU id (a number)
+ */
public int getCPU() {
return this.packetReader.getCPU();
}
+ /**
+ * Gets the filename of the stream being read
+ * @return The filename of the stream being read
+ */
+ public String getFilename() {
+ return streamInput.getFilename();
+ }
+
+ /*
+ * for internal use only
+ */
+ StreamInput getStreamInput() {
+ return streamInput;
+ }
+
// ------------------------------------------------------------------------
// Operations
// ------------------------------------------------------------------------
* @return If an event has been successfully read.
*/
public boolean readNextEvent() {
+
/*
* Change packet if needed
*/
if (!this.packetReader.hasMoreEvents()) {
- goToNextPacket();
+ final StreamInputPacketIndexEntry prevPacket = this.packetReader
+ .getCurrentPacket();
+ if (prevPacket != null) {
+ goToNextPacket();
+ final StreamInputPacketIndexEntry currentPacket = this.packetReader
+ .getCurrentPacket();
+ }
}
- /*
+ /*autogenerate javadoc getter setter
* If an event is available, read it.
*/
if (this.packetReader.hasMoreEvents()) {
try {
this.setCurrentEvent(this.packetReader.readNextEvent());
} catch (CTFReaderException e) {
- /* Some problem happened, we'll assume there is no more events */
+ /*
+ * Some problem happened, we'll assume that there are no more
+ * events
+ */
return false;
}
return true;
* Change the current packet of the packet reader to the next one.
*/
private void goToNextPacket() {
- if (getPacketIndexIt().hasNext()) {
- StreamInputPacketIndexEntry nextPacket = getPacketIndexIt().next();
- this.packetReader.setCurrentPacket(nextPacket);
+ packetIndex++;
+ if (getPacketSize() >= (packetIndex + 1)) {
+ this.packetReader.setCurrentPacket(getPacket());
} else {
- this.packetReader.setCurrentPacket(null);
+ try {
+ if (this.streamInput.addPacketHeaderIndex()) {
+ packetIndex = getPacketSize() - 1;
+ this.packetReader.setCurrentPacket(getPacket());
+
+ } else {
+ this.packetReader.setCurrentPacket(null);
+ }
+
+ } catch (CTFReaderException e) {
+ this.packetReader.setCurrentPacket(null);
+ }
}
}
+ /**
+ * @return
+ */
+ private int getPacketSize() {
+ return streamInput.getIndex().getEntries().size();
+ }
+
/**
* Changes the location of the trace file reader so that the current event
* is the first event with a timestamp greater than the given timestamp.
* The timestamp to seek to.
*/
public long seek(long timestamp) {
- long offset = 0 ;
- /*
- * Search in the index for the packet to search in.
- */
- this.packetIndexIt = this.streamInput.getIndex().search(timestamp);
+ long offset = 0;
+
+ gotoPacket(timestamp);
/*
- * Switch to this packet.
+ * index up to the desired timestamp.
*/
- goToNextPacket();
+ while ((this.packetReader.getCurrentPacket() != null)
+ && (this.packetReader.getCurrentPacket().getTimestampEnd() < timestamp)) {
+ try {
+ this.streamInput.addPacketHeaderIndex();
+ goToNextPacket();
+ } catch (CTFReaderException e) {
+ // do nothing here
+ }
+ }
+ if (this.packetReader.getCurrentPacket() == null) {
+ gotoPacket(timestamp);
+ }
/*
* Advance until A. we reached the end of the trace file (which means
*/
readNextEvent();
boolean done = (this.getCurrentEvent() == null);
- while (!done && (this.getCurrentEvent().timestamp < timestamp)) {
+ while (!done && (this.getCurrentEvent().getTimestamp() < timestamp)) {
readNextEvent();
done = (this.getCurrentEvent() == null);
- offset++ ;
+ offset++;
}
return offset;
}
+ /**
+ * @param timestamp
+ */
+ private void gotoPacket(long timestamp) {
+ this.packetIndex = this.streamInput.getIndex().search(timestamp)
+ .previousIndex();
+ /*
+ * Switch to this packet.
+ */
+ goToNextPacket();
+ }
- public long seekIndex(long index) throws CTFReaderException
- {
+ /**
+ * Seeks the last event of a stream and returns it.
+ */
+ public void goToLastEvent() {
/*
* Search in the index for the packet to search in.
*/
- this.packetIndexIt = this.streamInput.getIndex().searchIndex(index);
+ final int len = this.streamInput.getIndex().getEntries().size();
+
+ StreamInputPacketIndexEntry entry = null;
/*
- * Switch to this packet.
+ * Go to beginning of trace.
*/
- goToNextPacket();
+ seek(0);
/*
- * Read the first packet
+ * if the trace is empty.
*/
- readNextEvent();
+ if ((len == 0) || (this.packetReader.hasMoreEvents() == false)) {
+ /*
+ * This means the trace is empty. abort.
+ */
+ return;
+ }
/*
- * get the current index
+ * Go to the last packet that contains events.
*/
- if(this.packetReader.getCurrentPacket() == null){
- throw new CTFReaderException("Current packet null in index seek, did you index your trace yet?");
+ for (int pos = len - 1; pos > 0; pos--) {
+ packetIndex = pos;
+ this.packetReader.setCurrentPacket(getPacket());
+ if (this.packetReader.hasMoreEvents()) {
+ break;
+ }
}
- return this.packetReader.getCurrentPacket().getIndexBegin();
- }
-
- public void goToLastEvent() throws CTFReaderException {
- /*
- * Search in the index for the packet to search in.
- */
- int len = this.streamInput.getIndex().getEntries().size();
- StreamInputPacketIndexEntry entry = this.streamInput.getIndex().getEntries().get(len-1);
- seek(entry.getTimestampEnd() - 1 );
/*
* Go until the end of that packet
*/
- while (this.packetReader.hasMoreEvents()) {
- this.packetReader.readNextEvent();
+ EventDefinition prevEvent = null;
+ while (this.currentEvent != null) {
+ prevEvent = this.currentEvent;
+ this.readNextEvent();
}
+ /*
+ * Go back to the previous event
+ */
+ this.setCurrentEvent(prevEvent);
}
+ /**
+ * @return the parent
+ */
+ public CTFTraceReader getParent() {
+ return parent;
+ }
+
+ /**
+ * @param parent
+ * the parent to set
+ */
+ public void setParent(CTFTraceReader parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Sets the current event in a stream input reader
+ * @param currentEvent the event to set
+ */
public void setCurrentEvent(EventDefinition currentEvent) {
this.currentEvent = currentEvent;
}
/**
* @return the packetIndexIt
*/
- private ListIterator<StreamInputPacketIndexEntry> getPacketIndexIt() {
- return packetIndexIt;
+ private int getPacketIndex() {
+ return packetIndex;
+ }
+
+ private StreamInputPacketIndexEntry getPacket() {
+ return streamInput.getIndex().getEntries().get(getPacketIndex());
}
/**
return packetReader;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = (prime * result) + name;
+ result = (prime * result)
+ + ((streamInput == null) ? 0 : streamInput.hashCode());
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof StreamInputReader)) {
+ return false;
+ }
+ StreamInputReader other = (StreamInputReader) obj;
+ if (name != other.name) {
+ return false;
+ }
+ if (streamInput == null) {
+ if (other.streamInput != null) {
+ return false;
+ }
+ } else if (!streamInput.equals(other.streamInput)) {
+ return false;
+ }
+ return true;
+ }
+
}