1 /*******************************************************************************
2 * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
9 * Contributors: Matthew Khouzam - Initial API and implementation
10 * Contributors: Simon Marchi - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.ctf
.core
.trace
;
15 import java
.nio
.ByteOrder
;
17 import org
.eclipse
.linuxtools
.ctf
.core
.event
.EventDefinition
;
18 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDefinition
;
19 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.trace
.StreamInput
;
20 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.trace
.StreamInputPacketIndexEntry
;
23 * A CTF trace event reader. Reads the events of a trace file.
26 * @author Matthew Khouzam
27 * @author Simon Marchi
29 public class StreamInputReader
{
31 // ------------------------------------------------------------------------
33 // ------------------------------------------------------------------------
36 * The StreamInput we are reading.
38 private final StreamInput streamInput
;
41 * The packet reader used to read packets from this trace file.
43 private final StreamInputPacketReader packetReader
;
46 * Iterator on the packet index
48 private int packetIndex
;
51 * Reference to the current event of this trace file (iow, the last on that
52 * was read, the next one to be returned)
54 private EventDefinition currentEvent
= null;
58 private CTFTraceReader parent
;
60 @SuppressWarnings("unused")
61 private final long prevIndex
;
63 // ------------------------------------------------------------------------
65 // ------------------------------------------------------------------------
68 * Constructs a StreamInputReader that reads a StreamInput.
71 * The StreamInput to read.
73 public StreamInputReader(StreamInput streamInput
) {
74 this.streamInput
= streamInput
;
75 this.packetReader
= new StreamInputPacketReader(this);
77 * Get the iterator on the packet index.
83 * Make first packet the current one.
88 // ------------------------------------------------------------------------
89 // Getters/Setters/Predicates
90 // ------------------------------------------------------------------------
93 * Gets the current event in this stream
95 * @return the current event in the stream, null if the stream is
96 * finished/empty/malformed
98 public EventDefinition
getCurrentEvent() {
99 return this.currentEvent
;
103 * gets the current packet context
105 * @return the current packet context (size, lost events and such)
107 public StructDefinition
getCurrentPacketContext() {
108 return this.packetReader
.getStreamPacketContextDef();
112 * Gets the byte order for a trace
114 * @return the trace byte order
116 public ByteOrder
getByteOrder() {
117 return streamInput
.getStream().getTrace().getByteOrder();
121 * Gets the name of the stream (it's an id and a number)
123 * @return gets the stream name (it's a number)
125 public int getName() {
130 * Sets the name of the stream
133 * the name of the stream, (it's a number)
135 public void setName(int name
) {
140 * Gets the CPU of a stream. It's the same as the one in /proc or running
141 * the asm CPUID instruction
143 * @return The CPU id (a number)
145 public int getCPU() {
146 return this.packetReader
.getCPU();
150 * Gets the filename of the stream being read
151 * @return The filename of the stream being read
153 public String
getFilename() {
154 return streamInput
.getFilename();
158 * for internal use only
160 StreamInput
getStreamInput() {
164 // ------------------------------------------------------------------------
166 // ------------------------------------------------------------------------
168 * Reads the next event in the current event variable.
170 * @return If an event has been successfully read.
172 public boolean readNextEvent() {
175 * Change packet if needed
177 if (!this.packetReader
.hasMoreEvents()) {
178 final StreamInputPacketIndexEntry prevPacket
= this.packetReader
180 if (prevPacket
!= null) {
182 @SuppressWarnings("unused")
183 final StreamInputPacketIndexEntry currentPacket
= this.packetReader
.getCurrentPacket();
187 /*autogenerate javadoc getter setter
188 * If an event is available, read it.
190 if (this.packetReader
.hasMoreEvents()) {
192 this.setCurrentEvent(this.packetReader
.readNextEvent());
193 } catch (CTFReaderException e
) {
195 * Some problem happened, we'll assume that there are no more
202 this.setCurrentEvent(null);
207 * Change the current packet of the packet reader to the next one.
209 private void goToNextPacket() {
211 if (getPacketSize() >= (packetIndex
+ 1)) {
212 this.packetReader
.setCurrentPacket(getPacket());
215 if (this.streamInput
.addPacketHeaderIndex()) {
216 packetIndex
= getPacketSize() - 1;
217 this.packetReader
.setCurrentPacket(getPacket());
220 this.packetReader
.setCurrentPacket(null);
223 } catch (CTFReaderException e
) {
224 this.packetReader
.setCurrentPacket(null);
232 private int getPacketSize() {
233 return streamInput
.getIndex().getEntries().size();
237 * Changes the location of the trace file reader so that the current event
238 * is the first event with a timestamp greater than the given timestamp.
241 * The timestamp to seek to.
242 * @return The offset compared to the current position
244 public long seek(long timestamp
) {
247 gotoPacket(timestamp
);
250 * index up to the desired timestamp.
252 while ((this.packetReader
.getCurrentPacket() != null)
253 && (this.packetReader
.getCurrentPacket().getTimestampEnd() < timestamp
)) {
255 this.streamInput
.addPacketHeaderIndex();
257 } catch (CTFReaderException e
) {
261 if (this.packetReader
.getCurrentPacket() == null) {
262 gotoPacket(timestamp
);
266 * Advance until A. we reached the end of the trace file (which means
267 * the given timestamp is after the last event), or B. we found the
268 * first event with a timestamp greater than the given timestamp.
271 boolean done
= (this.getCurrentEvent() == null);
272 while (!done
&& (this.getCurrentEvent().getTimestamp() < timestamp
)) {
274 done
= (this.getCurrentEvent() == null);
283 private void gotoPacket(long timestamp
) {
284 this.packetIndex
= this.streamInput
.getIndex().search(timestamp
)
287 * Switch to this packet.
293 * Seeks the last event of a stream and returns it.
295 public void goToLastEvent() {
297 * Search in the index for the packet to search in.
299 final int len
= this.streamInput
.getIndex().getEntries().size();
301 @SuppressWarnings("unused")
302 StreamInputPacketIndexEntry entry
= null;
304 * Go to beginning of trace.
308 * if the trace is empty.
310 if ((len
== 0) || (this.packetReader
.hasMoreEvents() == false)) {
312 * This means the trace is empty. abort.
317 * Go to the last packet that contains events.
319 for (int pos
= len
- 1; pos
> 0; pos
--) {
321 this.packetReader
.setCurrentPacket(getPacket());
322 if (this.packetReader
.hasMoreEvents()) {
328 * Go until the end of that packet
330 EventDefinition prevEvent
= null;
331 while (this.currentEvent
!= null) {
332 prevEvent
= this.currentEvent
;
333 this.readNextEvent();
336 * Go back to the previous event
338 this.setCurrentEvent(prevEvent
);
344 public CTFTraceReader
getParent() {
352 public void setParent(CTFTraceReader parent
) {
353 this.parent
= parent
;
357 * Sets the current event in a stream input reader
358 * @param currentEvent the event to set
360 public void setCurrentEvent(EventDefinition currentEvent
) {
361 this.currentEvent
= currentEvent
;
365 * @return the packetIndexIt
367 private int getPacketIndex() {
371 private StreamInputPacketIndexEntry
getPacket() {
372 return streamInput
.getIndex().getEntries().get(getPacketIndex());
376 * @return the packetReader
378 public StreamInputPacketReader
getPacketReader() {
385 * @see java.lang.Object#hashCode()
388 public int hashCode() {
389 final int prime
= 31;
391 result
= (prime
* result
) + name
;
392 result
= (prime
* result
)
393 + ((streamInput
== null) ?
0 : streamInput
.hashCode());
400 * @see java.lang.Object#equals(java.lang.Object)
403 public boolean equals(Object obj
) {
410 if (!(obj
instanceof StreamInputReader
)) {
413 StreamInputReader other
= (StreamInputReader
) obj
;
414 if (name
!= other
.name
) {
417 if (streamInput
== null) {
418 if (other
.streamInput
!= null) {
421 } else if (!streamInput
.equals(other
.streamInput
)) {