/*******************************************************************************
- * 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
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
- * Contributors: Matthew Khouzam - Initial API and implementation
- * Contributors: Alexandre Montplaisir - Initial API and implementation
+ * Contributors:
+ * Matthew Khouzam - Initial API and implementation
+ * Alexandre Montplaisir - Initial API and implementation
*******************************************************************************/
package org.eclipse.linuxtools.ctf.core.trace;
import java.util.Collection;
-import java.util.HashMap;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.Vector;
import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
import org.eclipse.linuxtools.internal.ctf.core.Activator;
-import org.eclipse.linuxtools.internal.ctf.core.trace.Stream;
-import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInput;
-import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputReaderTimestampComparator;
/**
- * Reads the events of a trace.
+ * A CTF trace reader. Reads the events of a trace.
+ *
+ * @version 1.0
+ * @author Matthew Khouzam
+ * @author Alexandre Montplaisir
*/
-
public class CTFTraceReader {
// ------------------------------------------------------------------------
/**
* Array to count the number of event per trace file.
*/
- private int[] eventCountPerTraceFile;
+ private long[] eventCountPerTraceFile;
/**
* Timestamp of the first event in the trace
*/
private long endTime;
- /**
- * Current event index
- */
- private long fIndex;
-
- private final HashMap<Integer, Long> startIndex;
-
// ------------------------------------------------------------------------
// Constructors
// ------------------------------------------------------------------------
*
* @param trace
* The trace to read from.
- * @throws CTFReaderException
*/
public CTFTraceReader(CTFTrace trace) {
this.trace = trace;
+ streamInputReaders.clear();
/**
* Create the trace file readers.
populateStreamInputReaderHeap();
/**
- * Get the start Time of this trace
- * bear in mind that the trace could be empty.
+ * Get the start Time of this trace bear in mind that the trace could be
+ * empty.
*/
this.startTime = 0;// prio.peek().getPacketReader().getCurrentPacket().getTimestampBegin();
if (hasMoreEvents()) {
this.startTime = prio.peek().getCurrentEvent().getTimestamp();
- this.endTime = this.startTime;
- this.fIndex = 0;
+ this.setEndTime(this.startTime);
}
- startIndex = new HashMap<Integer, Long>();
}
/**
* Copy constructor
+ *
+ * @return The new CTFTraceReader
*/
public CTFTraceReader copyFrom() {
CTFTraceReader newReader = null;
newReader = new CTFTraceReader(this.trace);
newReader.startTime = this.startTime;
- newReader.endTime = this.endTime;
+ newReader.setEndTime(this.endTime);
return newReader;
}
+ /**
+ * Dispose the CTFTraceReader
+ * @since 2.0
+ */
+ public void dispose() {
+ for (StreamInputReader reader : streamInputReaders) {
+ if (reader != null) {
+ reader.dispose();
+ }
+ }
+ streamInputReaders.clear();
+ }
+
// ------------------------------------------------------------------------
// Getters/Setters/Predicates
// ------------------------------------------------------------------------
}
/**
- * @return the index
+ * Set the trace's end time
+ *
+ * @param endTime
+ * The end time to use
*/
- public long getIndex() {
- return fIndex;
+ protected void setEndTime(long endTime) {
+ this.endTime = endTime;
}
+
// ------------------------------------------------------------------------
// Operations
// ------------------------------------------------------------------------
/*
* Create the array to count the number of event per trace file.
*/
- this.eventCountPerTraceFile = new int[this.streamInputReaders.size()];
+ this.eventCountPerTraceFile = new long[this.streamInputReaders.size()];
}
/**
* Add each trace file reader in the priority queue, if we are able
* to read an event from it.
*/
+ reader.setParent(this);
if (reader.readNextEvent()) {
this.prio.add(reader);
if (top == null) {
return false;
}
- /*
- * index if needed
- */
- if (hasMoreEvents()) {
- StreamInputPacketReader packetReader = top.getPacketReader();
- boolean packetHasMoreEvents = packetReader.hasMoreEvents();
- StreamInputPacketIndexEntry currentPacket = packetReader
- .getCurrentPacket();
- if (!packetHasMoreEvents) {
- int n = this.streamInputReaders.indexOf(top);
- if (!startIndex.containsKey(n)) {
- startIndex.put(n, 0L);
- }
- currentPacket.setIndexBegin(startIndex.get(n));
- currentPacket.setIndexEnd(fIndex);
- startIndex.put(n, fIndex + 1);
- }
- }
/*
* Read the next event of this reader.
*/
* Add it back in the queue.
*/
this.prio.add(top);
- final long topEnd = top.getCurrentEvent().getTimestamp();
- this.endTime = Math.max(topEnd, this.endTime);
+ final long topEnd = this.trace.timestampCyclesToNanos(top.getCurrentEvent().getTimestamp());
+ this.setEndTime(Math.max(topEnd, this.getEndTime()));
this.eventCountPerTraceFile[top.getName()]++;
- /*
- * increment the index
- */
- fIndex++;
- }
- boolean hasMoreEvents = hasMoreEvents();
+ if (top.getCurrentEvent() != null) {
+ this.endTime = Math.max(top.getCurrentEvent().getTimestamp(),
+ this.endTime);
+ }
+ }
/*
* If there is no reader in the queue, it means the trace reader reached
* the end of the trace.
*/
- return hasMoreEvents;
+ return hasMoreEvents();
}
/**
* Go to the last event in the trace.
- *
- * @throws CTFReaderException
*/
- public void goToLastEvent() throws CTFReaderException {
-
- for (StreamInputReader streamInputReader : this.streamInputReaders) {
- /*
- * Seek the trace reader.
- */
- streamInputReader.goToLastEvent();
- }
- int count = prio.size();
- for (int i = 0; i < (count - 1); i++) {
- /*
- * Cull all the streams aside from the last one
- */
- prio.poll();
+ public void goToLastEvent() {
+ seek(this.getEndTime());
+ while (this.prio.size() > 1) {
+ this.advance();
}
}
* Remove all the trace readers from the priority queue
*/
this.prio.clear();
- fIndex = 0;
- long offset = 0;
for (StreamInputReader streamInputReader : this.streamInputReaders) {
/*
* Seek the trace reader.
*/
- offset += streamInputReader.seek(timestamp);
+ streamInputReader.seek(timestamp);
/*
* Add it to the priority queue if there is a current event.
for (StreamInputReader streamInputReader : this.streamInputReaders) {
if (streamInputReader.getCurrentEvent() != null) {
this.prio.add(streamInputReader);
- fIndex = Math.max(fIndex, streamInputReader.getPacketReader()
- .getCurrentPacket().getIndexBegin()
- + offset);
- }
- }
- return hasMoreEvents();
- }
-
- public boolean seekIndex(long index) {
- this.prio.clear();
-
- long tempIndex = Long.MIN_VALUE;
- long tempTimestamp = Long.MIN_VALUE;
- try {
- for (StreamInputReader streamInputReader : this.streamInputReaders) {
- /*
- * Seek the trace reader.
- */
- final long streamIndex = streamInputReader.seekIndex(index);
- if (streamInputReader.getCurrentEvent() != null) {
- tempIndex = Math.max(tempIndex, streamIndex);
- EventDefinition currentEvent = streamInputReader
- .getCurrentEvent();
- /*
- * Maybe we're at the beginning of a trace.
- */
- if (currentEvent == null) {
- streamInputReader.readNextEvent();
- currentEvent = streamInputReader.getCurrentEvent();
- }
- if (currentEvent != null) {
- tempTimestamp = Math.max(tempTimestamp,
- currentEvent.getTimestamp());
- } else {
- /*
- * probably beyond the last event
- */
- tempIndex = goToZero();
- }
- }
-
- }
- } catch (CTFReaderException e) {
- /*
- * Important, if it failed, it's because it's not yet indexed, so we
- * have to manually advance to the right value.
- */
- tempIndex = goToZero();
- }
- for (StreamInputReader streamInputReader : this.streamInputReaders) {
- /*
- * Add it to the priority queue if there is a current event.
- */
-
- if (streamInputReader.getCurrentEvent() != null) {
- this.prio.add(streamInputReader);
- }
- }
- if (tempIndex == Long.MAX_VALUE) {
- tempIndex = 0;
- }
- long pos = tempIndex;
- if (index > tempIndex) {
- /*
- * advance for offset
- */
- while ((prio.peek().getCurrentEvent().getTimestamp() < tempTimestamp)
- && hasMoreEvents()) {
- this.advance();
- }
- for (pos = tempIndex; (pos < index) && hasMoreEvents(); pos++) {
- this.advance();
}
}
- this.fIndex = pos;
return hasMoreEvents();
}
+// /**
+// * Go to the first entry of a trace
+// *
+// * @return 0, the first index.
+// */
+// private long goToZero() {
+// long tempIndex;
+// for (StreamInputReader streamInputReader : this.streamInputReaders) {
+// /*
+// * Seek the trace reader.
+// */
+// streamInputReader.seek(0);
+// }
+// tempIndex = 0;
+// return tempIndex;
+// }
+
/**
- * Go to the first entry of a trace
+ * gets the stream with the oldest event
*
- * @return 0, the first index.
+ * @return the stream with the oldest event
*/
- private long goToZero() {
- long tempIndex;
- for (StreamInputReader streamInputReader : this.streamInputReaders) {
- /*
- * Seek the trace reader.
- */
- streamInputReader.seek(0);
- }
- tempIndex = 0;
- return tempIndex;
- }
-
public StreamInputReader getTopStream() {
return this.prio.peek();
}
return;
}
- for (int i : this.eventCountPerTraceFile) {
+ for (long i : this.eventCountPerTraceFile) {
numEvents += i;
}
for (int j = 0; j < this.eventCountPerTraceFile.length; j++) {
StreamInputReader se = this.streamInputReaders.get(j);
- int len = (width * this.eventCountPerTraceFile[se.getName()])
+ long len = (width * this.eventCountPerTraceFile[se.getName()])
/ numEvents;
StringBuilder sb = new StringBuilder(se.getFilename() + "\t["); //$NON-NLS-1$
sb.append('+');
}
- for (int i = len; i < width; i++) {
+ for (long i = len; i < width; i++) {
sb.append(' ');
}
sb.append("]\t" + this.eventCountPerTraceFile[se.getName()] + " Events"); //$NON-NLS-1$//$NON-NLS-2$
- Activator.getDefault().log(sb.toString());
+ Activator.log(sb.toString());
}
}
+ /**
+ * gets the last event timestamp that was read. This is NOT necessarily the
+ * last event in a trace, just the last one read so far.
+ *
+ * @return the last event
+ */
public long getEndTime() {
return this.endTime;
}
public int hashCode() {
final int prime = 31;
int result = 1;
- result = (prime * result) + (int) (endTime ^ (endTime >>> 32));
result = (prime * result) + (int) (startTime ^ (startTime >>> 32));
- result = (prime * result)
- + ((streamInputReaders == null) ? 0 : streamInputReaders
- .hashCode());
+ result = (prime * result) + streamInputReaders.hashCode();
result = (prime * result) + ((trace == null) ? 0 : trace.hashCode());
return result;
}
return false;
}
CTFTraceReader other = (CTFTraceReader) obj;
- if (endTime != other.endTime) {
- return false;
- }
- if (startTime != other.startTime) {
- return false;
- }
- if (streamInputReaders == null) {
- if (other.streamInputReaders != null) {
- return false;
- }
- } else if (!streamInputReaders.equals(other.streamInputReaders)) {
+ if (!streamInputReaders.equals(other.streamInputReaders)) {
return false;
}
if (trace == null) {
return true;
}
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#toString()
- */
@Override
public String toString() {
/* Only for debugging, shouldn't be externalized */
return "CTFTraceReader [trace=" + trace + ']'; //$NON-NLS-1$
}
+ /**
+ * Gets the parent trace
+ *
+ * @return the parent trace
+ */
public CTFTrace getTrace() {
return trace;
}