1 /*******************************************************************************
2 * Copyright (c) 2011, 2013 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
.StreamInputPacketIndexEntry
;
22 * A CTF trace event reader. Reads the events of a trace file.
25 * @author Matthew Khouzam
26 * @author Simon Marchi
28 public class StreamInputReader
{
30 // ------------------------------------------------------------------------
32 // ------------------------------------------------------------------------
35 * The StreamInput we are reading.
37 private final StreamInput streamInput
;
40 * The packet reader used to read packets from this trace file.
42 private final StreamInputPacketReader packetReader
;
45 * Iterator on the packet index
47 private int packetIndex
;
50 * Reference to the current event of this trace file (iow, the last on that
51 * was read, the next one to be returned)
53 private EventDefinition currentEvent
= null;
57 private CTFTraceReader parent
;
60 // ------------------------------------------------------------------------
62 // ------------------------------------------------------------------------
65 * Constructs a StreamInputReader that reads a StreamInput.
68 * The StreamInput to read.
71 public StreamInputReader(StreamInput streamInput
) {
72 this.streamInput
= streamInput
;
73 this.packetReader
= new StreamInputPacketReader(this);
75 * Get the iterator on the packet index.
79 * Make first packet the current one.
85 * Dispose the StreamInputReader
88 public void dispose() {
89 packetReader
.dispose();
92 // ------------------------------------------------------------------------
93 // Getters/Setters/Predicates
94 // ------------------------------------------------------------------------
97 * Gets the current event in this stream
99 * @return the current event in the stream, null if the stream is
100 * finished/empty/malformed
102 public EventDefinition
getCurrentEvent() {
103 return this.currentEvent
;
107 * gets the current packet context
109 * @return the current packet context (size, lost events and such)
111 public StructDefinition
getCurrentPacketContext() {
112 return this.packetReader
.getStreamPacketContextDef();
116 * Gets the byte order for a trace
118 * @return the trace byte order
120 public ByteOrder
getByteOrder() {
121 return streamInput
.getStream().getTrace().getByteOrder();
125 * Gets the name of the stream (it's an id and a number)
127 * @return gets the stream name (it's a number)
129 public int getName() {
134 * Sets the name of the stream
137 * the name of the stream, (it's a number)
139 public void setName(int name
) {
144 * Gets the CPU of a stream. It's the same as the one in /proc or running
145 * the asm CPUID instruction
147 * @return The CPU id (a number)
149 public int getCPU() {
150 return this.packetReader
.getCPU();
154 * Gets the filename of the stream being read
155 * @return The filename of the stream being read
157 public String
getFilename() {
158 return streamInput
.getFilename();
162 * for internal use only
164 StreamInput
getStreamInput() {
168 // ------------------------------------------------------------------------
170 // ------------------------------------------------------------------------
172 * Reads the next event in the current event variable.
174 * @return If an event has been successfully read.
176 public boolean readNextEvent() {
179 * Change packet if needed
181 if (!this.packetReader
.hasMoreEvents()) {
182 final StreamInputPacketIndexEntry prevPacket
= this.packetReader
184 if (prevPacket
!= null) {
190 * If an event is available, read it.
192 if (this.packetReader
.hasMoreEvents()) {
194 this.setCurrentEvent(this.packetReader
.readNextEvent());
195 } catch (CTFReaderException e
) {
197 * Some problem happened, we'll assume that there are no more
204 this.setCurrentEvent(null);
209 * Change the current packet of the packet reader to the next one.
211 private void goToNextPacket() {
213 if (getPacketSize() >= (packetIndex
+ 1)) {
214 this.packetReader
.setCurrentPacket(getPacket());
217 if (this.streamInput
.addPacketHeaderIndex()) {
218 packetIndex
= getPacketSize() - 1;
219 this.packetReader
.setCurrentPacket(getPacket());
222 this.packetReader
.setCurrentPacket(null);
225 } catch (CTFReaderException e
) {
226 this.packetReader
.setCurrentPacket(null);
234 private int getPacketSize() {
235 return streamInput
.getIndex().getEntries().size();
239 * Changes the location of the trace file reader so that the current event
240 * is the first event with a timestamp greater than the given timestamp.
243 * The timestamp to seek to.
244 * @return The offset compared to the current position
246 public long seek(long timestamp
) {
249 gotoPacket(timestamp
);
252 * index up to the desired timestamp.
254 while ((this.packetReader
.getCurrentPacket() != null)
255 && (this.packetReader
.getCurrentPacket().getTimestampEnd() < timestamp
)) {
257 this.streamInput
.addPacketHeaderIndex();
259 } catch (CTFReaderException e
) {
263 if (this.packetReader
.getCurrentPacket() == null) {
264 gotoPacket(timestamp
);
268 * Advance until A. we reached the end of the trace file (which means
269 * the given timestamp is after the last event), or B. we found the
270 * first event with a timestamp greater than the given timestamp.
273 boolean done
= (this.getCurrentEvent() == null);
274 while (!done
&& (this.getCurrentEvent().getTimestamp() < timestamp
)) {
276 done
= (this.getCurrentEvent() == null);
285 private void gotoPacket(long timestamp
) {
286 this.packetIndex
= this.streamInput
.getIndex().search(timestamp
)
289 * Switch to this packet.
295 * Seeks the last event of a stream and returns it.
297 public void goToLastEvent() {
299 * Search in the index for the packet to search in.
301 final int len
= this.streamInput
.getIndex().getEntries().size();
303 @SuppressWarnings("unused")
304 StreamInputPacketIndexEntry entry
= null;
306 * Go to beginning of trace.
310 * if the trace is empty.
312 if ((len
== 0) || (this.packetReader
.hasMoreEvents() == false)) {
314 * This means the trace is empty. abort.
319 * Go to the last packet that contains events.
321 for (int pos
= len
- 1; pos
> 0; pos
--) {
323 this.packetReader
.setCurrentPacket(getPacket());
324 if (this.packetReader
.hasMoreEvents()) {
330 * Go until the end of that packet
332 EventDefinition prevEvent
= null;
333 while (this.currentEvent
!= null) {
334 prevEvent
= this.currentEvent
;
335 this.readNextEvent();
338 * Go back to the previous event
340 this.setCurrentEvent(prevEvent
);
346 public CTFTraceReader
getParent() {
354 public void setParent(CTFTraceReader parent
) {
355 this.parent
= parent
;
359 * Sets the current event in a stream input reader
360 * @param currentEvent the event to set
362 public void setCurrentEvent(EventDefinition currentEvent
) {
363 this.currentEvent
= currentEvent
;
367 * @return the packetIndexIt
369 private int getPacketIndex() {
373 private StreamInputPacketIndexEntry
getPacket() {
374 return streamInput
.getIndex().getEntries().get(getPacketIndex());
378 * @return the packetReader
380 public StreamInputPacketReader
getPacketReader() {
385 public int hashCode() {
386 final int prime
= 31;
388 result
= (prime
* result
) + name
;
389 result
= (prime
* result
)
390 + ((streamInput
== null) ?
0 : streamInput
.hashCode());
395 public boolean equals(Object obj
) {
402 if (!(obj
instanceof StreamInputReader
)) {
405 StreamInputReader other
= (StreamInputReader
) obj
;
406 if (name
!= other
.name
) {
409 if (streamInput
== null) {
410 if (other
.streamInput
!= null) {
413 } else if (!streamInput
.equals(other
.streamInput
)) {
420 public String
toString() {
421 // this helps debugging
422 return this.name
+ ' ' + this.currentEvent
.toString();