1 /*******************************************************************************
2 * Copyright (c) 2011, 2014 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
.IEventDeclaration
;
19 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDeclaration
;
20 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.trace
.StreamInputPacketIndexEntry
;
22 import com
.google
.common
.collect
.ImmutableSet
;
25 * A CTF trace event reader. Reads the events of a trace file.
27 * @author Matthew Khouzam
28 * @author Simon Marchi
31 public class CTFStreamInputReader
implements AutoCloseable
{
33 // ------------------------------------------------------------------------
35 // ------------------------------------------------------------------------
38 * The StreamInput we are reading.
40 private final CTFStreamInput fStreamInput
;
43 * The packet reader used to read packets from this trace file.
45 private final CTFStreamInputPacketReader fPacketReader
;
48 * Iterator on the packet index
50 private int fPacketIndex
;
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 fCurrentEvent
= null;
60 private CTFTraceReader fParent
;
65 private boolean fLive
= false;
67 // ------------------------------------------------------------------------
69 // ------------------------------------------------------------------------
72 * Constructs a StreamInputReader that reads a StreamInput.
75 * The StreamInput to read.
76 * @throws CTFReaderException
79 public CTFStreamInputReader(CTFStreamInput streamInput
) throws CTFReaderException
{
80 fStreamInput
= streamInput
;
81 fPacketReader
= new CTFStreamInputPacketReader(this);
83 * Get the iterator on the packet index.
87 * Make first packet the current one.
93 * Dispose the StreamInputReader
97 fPacketReader
.close();
100 // ------------------------------------------------------------------------
101 // Getters/Setters/Predicates
102 // ------------------------------------------------------------------------
105 * Gets the current event in this stream
107 * @return the current event in the stream, null if the stream is
108 * finished/empty/malformed
110 public EventDefinition
getCurrentEvent() {
111 return fCurrentEvent
;
115 * Gets the byte order for a trace
117 * @return the trace byte order
119 public ByteOrder
getByteOrder() {
120 return fStreamInput
.getStream().getTrace().getByteOrder();
124 * Gets the name of the stream (it's an id and a number)
126 * @return gets the stream name (it's a number)
128 public int getName() {
133 * Sets the name of the stream
136 * the name of the stream, (it's a number)
138 public void setName(int name
) {
143 * Gets the CPU of a stream. It's the same as the one in /proc or running
144 * the asm CPUID instruction
146 * @return The CPU id (a number)
148 public int getCPU() {
149 return fPacketReader
.getCPU();
153 * Gets the filename of the stream being read
155 * @return The filename of the stream being read
157 public String
getFilename() {
158 return fStreamInput
.getFilename();
162 * for internal use only
164 CTFStreamInput
getStreamInput() {
169 * Gets the event definition set for this StreamInput
171 * @return Unmodifiable set with the event definitions
173 public Iterable
<IEventDeclaration
> getEventDeclarations() {
174 return ImmutableSet
.copyOf(fStreamInput
.getStream().getEvents().values());
178 * Set the trace to live mode
181 * whether the trace is read live or not
183 public void setLive(boolean live
) {
188 * Get if the trace is to read live or not
190 * @return whether the trace is live or not
192 public boolean isLive() {
197 * Get the event context of the stream
199 * @return the event context declaration of the stream
201 public StructDeclaration
getStreamEventContextDecl() {
202 return getStreamInput().getStream().getEventContextDecl();
205 // ------------------------------------------------------------------------
207 // ------------------------------------------------------------------------
209 * Reads the next event in the current event variable.
211 * @return If an event has been successfully read.
212 * @throws CTFReaderException
215 public CTFResponse
readNextEvent() throws CTFReaderException
{
218 * Change packet if needed
220 if (!fPacketReader
.hasMoreEvents()) {
221 final StreamInputPacketIndexEntry prevPacket
= fPacketReader
223 if (prevPacket
!= null || fLive
) {
230 * If an event is available, read it.
232 if (fPacketReader
.hasMoreEvents()) {
233 setCurrentEvent(fPacketReader
.readNextEvent());
234 return CTFResponse
.OK
;
236 this.setCurrentEvent(null);
237 return fLive ? CTFResponse
.WAIT
: CTFResponse
.FINISH
;
241 * Change the current packet of the packet reader to the next one.
243 * @throws CTFReaderException
246 private void goToNextPacket() throws CTFReaderException
{
248 // did we already index the packet?
249 if (getPacketSize() >= (fPacketIndex
+ 1)) {
250 fPacketReader
.setCurrentPacket(getPacket());
252 // go to the next packet if there is one, index it at the same time
253 if (fStreamInput
.addPacketHeaderIndex()) {
254 fPacketIndex
= getPacketSize() - 1;
255 fPacketReader
.setCurrentPacket(getPacket());
258 fPacketReader
.setCurrentPacket(null);
266 private int getPacketSize() {
267 return fStreamInput
.getIndex().getEntries().size();
271 * Changes the location of the trace file reader so that the current event
272 * is the first event with a timestamp greater or equal the given timestamp.
275 * The timestamp to seek to.
276 * @return The offset compared to the current position
277 * @throws CTFReaderException
280 public long seek(long timestamp
) throws CTFReaderException
{
283 gotoPacket(timestamp
);
286 * index up to the desired timestamp.
288 while ((fPacketReader
.getCurrentPacket() != null)
289 && (fPacketReader
.getCurrentPacket().getTimestampEnd() < timestamp
)) {
291 fStreamInput
.addPacketHeaderIndex();
293 } catch (CTFReaderException e
) {
297 if (fPacketReader
.getCurrentPacket() == null) {
298 gotoPacket(timestamp
);
302 * Advance until either of these conditions are met:
304 * - reached the end of the trace file (the given timestamp is after the
307 * - found the first event with a timestamp greater or equal the given
311 boolean done
= (this.getCurrentEvent() == null);
312 while (!done
&& (this.getCurrentEvent().getTimestamp() < timestamp
)) {
314 done
= (this.getCurrentEvent() == null);
323 * @throws CTFReaderException
326 private void gotoPacket(long timestamp
) throws CTFReaderException
{
327 fPacketIndex
= fStreamInput
.getIndex().search(timestamp
)
330 * Switch to this packet.
336 * Seeks the last event of a stream and returns it.
338 * @throws CTFReaderException
341 public void goToLastEvent() throws CTFReaderException
{
343 * Search in the index for the packet to search in.
345 final int len
= fStreamInput
.getIndex().getEntries().size();
348 * Go to beginning of trace.
352 * if the trace is empty.
354 if ((len
== 0) || (fPacketReader
.hasMoreEvents() == false)) {
356 * This means the trace is empty. abort.
361 * Go to the last packet that contains events.
363 for (int pos
= len
- 1; pos
> 0; pos
--) {
365 fPacketReader
.setCurrentPacket(getPacket());
366 if (fPacketReader
.hasMoreEvents()) {
372 * Go until the end of that packet
374 EventDefinition prevEvent
= null;
375 while (fCurrentEvent
!= null) {
376 prevEvent
= fCurrentEvent
;
377 this.readNextEvent();
380 * Go back to the previous event
382 this.setCurrentEvent(prevEvent
);
388 public CTFTraceReader
getParent() {
396 public void setParent(CTFTraceReader parent
) {
401 * Sets the current event in a stream input reader
403 * @param currentEvent
406 public void setCurrentEvent(EventDefinition currentEvent
) {
407 fCurrentEvent
= currentEvent
;
411 * @return the packetIndexIt
413 private int getPacketIndex() {
417 private StreamInputPacketIndexEntry
getPacket() {
418 return fStreamInput
.getIndex().getEntries().get(getPacketIndex());
422 * @return the packetReader
424 public CTFStreamInputPacketReader
getPacketReader() {
425 return fPacketReader
;
429 public int hashCode() {
430 final int prime
= 31;
432 result
= (prime
* result
) + fId
;
433 result
= (prime
* result
)
434 + ((fStreamInput
== null) ?
0 : fStreamInput
.hashCode());
439 public boolean equals(Object obj
) {
446 if (!(obj
instanceof CTFStreamInputReader
)) {
449 CTFStreamInputReader other
= (CTFStreamInputReader
) obj
;
450 if (fId
!= other
.fId
) {
453 if (fStreamInput
== null) {
454 if (other
.fStreamInput
!= null) {
457 } else if (!fStreamInput
.equals(other
.fStreamInput
)) {
464 public String
toString() {
465 // this helps debugging
466 return fId
+ ' ' + fCurrentEvent
.toString();