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
;
16 import java
.util
.Collections
;
17 import java
.util
.HashMap
;
20 import org
.eclipse
.linuxtools
.ctf
.core
.event
.EventDefinition
;
21 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDefinition
;
22 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.trace
.StreamInputPacketIndexEntry
;
25 * A CTF trace event reader. Reads the events of a trace file.
28 * @author Matthew Khouzam
29 * @author Simon Marchi
31 public class StreamInputReader
{
33 // ------------------------------------------------------------------------
35 // ------------------------------------------------------------------------
38 * The StreamInput we are reading.
40 private final StreamInput streamInput
;
43 * The packet reader used to read packets from this trace file.
45 private final StreamInputPacketReader packetReader
;
48 * Iterator on the packet index
50 private int packetIndex
;
53 * Reference to the current event of this trace file (iow, the last on that
54 * was read, the next one to be returned)
56 private EventDefinition currentEvent
= null;
60 private CTFTraceReader parent
;
62 /** Map of all the event types */
63 private final Map
<Long
, EventDefinition
> eventDefs
= new HashMap
<Long
,EventDefinition
>();
65 // ------------------------------------------------------------------------
67 // ------------------------------------------------------------------------
70 * Constructs a StreamInputReader that reads a StreamInput.
73 * The StreamInput to read.
76 public StreamInputReader(StreamInput streamInput
) {
77 this.streamInput
= streamInput
;
78 this.packetReader
= new StreamInputPacketReader(this);
80 * Get the iterator on the packet index.
84 * Make first packet the current one.
90 * Dispose the StreamInputReader
93 public void dispose() {
94 packetReader
.dispose();
97 // ------------------------------------------------------------------------
98 // Getters/Setters/Predicates
99 // ------------------------------------------------------------------------
102 * Gets the current event in this stream
104 * @return the current event in the stream, null if the stream is
105 * finished/empty/malformed
107 public EventDefinition
getCurrentEvent() {
108 return this.currentEvent
;
112 * gets the current packet context
114 * @return the current packet context (size, lost events and such)
116 public StructDefinition
getCurrentPacketContext() {
117 return this.packetReader
.getStreamPacketContextDef();
121 * Gets the byte order for a trace
123 * @return the trace byte order
125 public ByteOrder
getByteOrder() {
126 return streamInput
.getStream().getTrace().getByteOrder();
130 * Gets the name of the stream (it's an id and a number)
132 * @return gets the stream name (it's a number)
134 public int getName() {
139 * Sets the name of the stream
142 * the name of the stream, (it's a number)
144 public void setName(int name
) {
149 * Gets the CPU of a stream. It's the same as the one in /proc or running
150 * the asm CPUID instruction
152 * @return The CPU id (a number)
154 public int getCPU() {
155 return this.packetReader
.getCPU();
159 * Gets the filename of the stream being read
160 * @return The filename of the stream being read
162 public String
getFilename() {
163 return streamInput
.getFilename();
167 * for internal use only
169 StreamInput
getStreamInput() {
174 * Gets the event definition hashmap for this StreamInput
176 * @return Unmodifiable map with the event definitions
179 public Map
<Long
, EventDefinition
> getEventDefinitions() {
180 return Collections
.unmodifiableMap(eventDefs
);
184 * Add an event definition to this stream input reader.
187 * The id of the event definition. This will overwrite any
188 * existing definition with the same id.
190 * The matching event definition
193 public void addEventDefinition(Long id
, EventDefinition def
) {
194 eventDefs
.put(id
, def
);
197 // ------------------------------------------------------------------------
199 // ------------------------------------------------------------------------
201 * Reads the next event in the current event variable.
203 * @return If an event has been successfully read.
205 public boolean readNextEvent() {
208 * Change packet if needed
210 if (!this.packetReader
.hasMoreEvents()) {
211 final StreamInputPacketIndexEntry prevPacket
= this.packetReader
213 if (prevPacket
!= null) {
219 * If an event is available, read it.
221 if (this.packetReader
.hasMoreEvents()) {
223 this.setCurrentEvent(this.packetReader
.readNextEvent());
224 } catch (CTFReaderException e
) {
226 * Some problem happened, we'll assume that there are no more
233 this.setCurrentEvent(null);
238 * Change the current packet of the packet reader to the next one.
240 private void goToNextPacket() {
242 if (getPacketSize() >= (packetIndex
+ 1)) {
243 this.packetReader
.setCurrentPacket(getPacket());
246 if (this.streamInput
.addPacketHeaderIndex()) {
247 packetIndex
= getPacketSize() - 1;
248 this.packetReader
.setCurrentPacket(getPacket());
251 this.packetReader
.setCurrentPacket(null);
254 } catch (CTFReaderException e
) {
255 this.packetReader
.setCurrentPacket(null);
263 private int getPacketSize() {
264 return streamInput
.getIndex().getEntries().size();
268 * Changes the location of the trace file reader so that the current event
269 * is the first event with a timestamp greater than the given timestamp.
272 * The timestamp to seek to.
273 * @return The offset compared to the current position
275 public long seek(long timestamp
) {
278 gotoPacket(timestamp
);
281 * index up to the desired timestamp.
283 while ((this.packetReader
.getCurrentPacket() != null)
284 && (this.packetReader
.getCurrentPacket().getTimestampEnd() < timestamp
)) {
286 this.streamInput
.addPacketHeaderIndex();
288 } catch (CTFReaderException e
) {
292 if (this.packetReader
.getCurrentPacket() == null) {
293 gotoPacket(timestamp
);
297 * Advance until A. we reached the end of the trace file (which means
298 * the given timestamp is after the last event), or B. we found the
299 * first event with a timestamp greater than the given timestamp.
302 boolean done
= (this.getCurrentEvent() == null);
303 while (!done
&& (this.getCurrentEvent().getTimestamp() < timestamp
)) {
305 done
= (this.getCurrentEvent() == null);
314 private void gotoPacket(long timestamp
) {
315 this.packetIndex
= this.streamInput
.getIndex().search(timestamp
)
318 * Switch to this packet.
324 * Seeks the last event of a stream and returns it.
326 public void goToLastEvent() {
328 * Search in the index for the packet to search in.
330 final int len
= this.streamInput
.getIndex().getEntries().size();
332 @SuppressWarnings("unused")
333 StreamInputPacketIndexEntry entry
= null;
335 * Go to beginning of trace.
339 * if the trace is empty.
341 if ((len
== 0) || (this.packetReader
.hasMoreEvents() == false)) {
343 * This means the trace is empty. abort.
348 * Go to the last packet that contains events.
350 for (int pos
= len
- 1; pos
> 0; pos
--) {
352 this.packetReader
.setCurrentPacket(getPacket());
353 if (this.packetReader
.hasMoreEvents()) {
359 * Go until the end of that packet
361 EventDefinition prevEvent
= null;
362 while (this.currentEvent
!= null) {
363 prevEvent
= this.currentEvent
;
364 this.readNextEvent();
367 * Go back to the previous event
369 this.setCurrentEvent(prevEvent
);
375 public CTFTraceReader
getParent() {
383 public void setParent(CTFTraceReader parent
) {
384 this.parent
= parent
;
388 * Sets the current event in a stream input reader
389 * @param currentEvent the event to set
391 public void setCurrentEvent(EventDefinition currentEvent
) {
392 this.currentEvent
= currentEvent
;
396 * @return the packetIndexIt
398 private int getPacketIndex() {
402 private StreamInputPacketIndexEntry
getPacket() {
403 return streamInput
.getIndex().getEntries().get(getPacketIndex());
407 * @return the packetReader
409 public StreamInputPacketReader
getPacketReader() {
414 public int hashCode() {
415 final int prime
= 31;
417 result
= (prime
* result
) + name
;
418 result
= (prime
* result
)
419 + ((streamInput
== null) ?
0 : streamInput
.hashCode());
424 public boolean equals(Object obj
) {
431 if (!(obj
instanceof StreamInputReader
)) {
434 StreamInputReader other
= (StreamInputReader
) obj
;
435 if (name
!= other
.name
) {
438 if (streamInput
== null) {
439 if (other
.streamInput
!= null) {
442 } else if (!streamInput
.equals(other
.streamInput
)) {
449 public String
toString() {
450 // this helps debugging
451 return this.name
+ ' ' + this.currentEvent
.toString();