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
.jdt
.annotation
.NonNull
;
18 import org
.eclipse
.linuxtools
.ctf
.core
.event
.EventDefinition
;
19 import org
.eclipse
.linuxtools
.ctf
.core
.event
.IEventDeclaration
;
20 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDeclaration
;
21 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.trace
.StreamInputPacketIndexEntry
;
23 import com
.google
.common
.collect
.ImmutableList
;
26 * A CTF trace event reader. Reads the events of a trace file.
28 * @author Matthew Khouzam
29 * @author Simon Marchi
32 public class CTFStreamInputReader
implements AutoCloseable
{
34 // ------------------------------------------------------------------------
36 // ------------------------------------------------------------------------
39 * The StreamInput we are reading.
41 private final @NonNull CTFStreamInput fStreamInput
;
44 * The packet reader used to read packets from this trace file.
46 private final CTFStreamInputPacketReader fPacketReader
;
49 * Iterator on the packet index
51 private int fPacketIndex
;
54 * Reference to the current event of this trace file (iow, the last on that
55 * was read, the next one to be returned)
57 private EventDefinition fCurrentEvent
= null;
61 private CTFTraceReader fParent
;
66 private boolean fLive
= false;
68 // ------------------------------------------------------------------------
70 // ------------------------------------------------------------------------
73 * Constructs a StreamInputReader that reads a StreamInput.
76 * The StreamInput to read.
77 * @throws CTFReaderException
80 public CTFStreamInputReader(CTFStreamInput streamInput
) throws CTFReaderException
{
81 if (streamInput
== null) {
82 throw new IllegalArgumentException("streamInput cannot be null"); //$NON-NLS-1$
84 fStreamInput
= streamInput
;
85 fPacketReader
= new CTFStreamInputPacketReader(this);
87 * Get the iterator on the packet index.
91 * Make first packet the current one.
97 * Dispose the StreamInputReader
100 public void close() {
101 fPacketReader
.close();
104 // ------------------------------------------------------------------------
105 // Getters/Setters/Predicates
106 // ------------------------------------------------------------------------
109 * Gets the current event in this stream
111 * @return the current event in the stream, null if the stream is
112 * finished/empty/malformed
114 public EventDefinition
getCurrentEvent() {
115 return fCurrentEvent
;
119 * Gets the byte order for a trace
121 * @return the trace byte order
123 public ByteOrder
getByteOrder() {
124 return fStreamInput
.getStream().getTrace().getByteOrder();
128 * Gets the name of the stream (it's an id and a number)
130 * @return gets the stream name (it's a number)
132 public int getName() {
137 * Sets the name of the stream
140 * the name of the stream, (it's a number)
142 public void setName(int name
) {
147 * Gets the CPU of a stream. It's the same as the one in /proc or running
148 * the asm CPUID instruction
150 * @return The CPU id (a number)
152 public int getCPU() {
153 return fPacketReader
.getCPU();
157 * Gets the filename of the stream being read
159 * @return The filename of the stream being read
161 public String
getFilename() {
162 return fStreamInput
.getFilename();
166 * for internal use only
168 CTFStreamInput
getStreamInput() {
173 * Gets the event definition set for this StreamInput
175 * @return Unmodifiable set with the event definitions
177 public Iterable
<IEventDeclaration
> getEventDeclarations() {
178 return ImmutableList
.copyOf(fStreamInput
.getStream().getEventDeclarations());
182 * Set the trace to live mode
185 * whether the trace is read live or not
187 public void setLive(boolean live
) {
192 * Get if the trace is to read live or not
194 * @return whether the trace is live or not
196 public boolean isLive() {
201 * Get the event context of the stream
203 * @return the event context declaration of the stream
205 public StructDeclaration
getStreamEventContextDecl() {
206 return getStreamInput().getStream().getEventContextDecl();
209 // ------------------------------------------------------------------------
211 // ------------------------------------------------------------------------
213 * Reads the next event in the current event variable.
215 * @return If an event has been successfully read.
216 * @throws CTFReaderException
219 public CTFResponse
readNextEvent() throws CTFReaderException
{
222 * Change packet if needed
224 if (!fPacketReader
.hasMoreEvents()) {
225 final StreamInputPacketIndexEntry prevPacket
= fPacketReader
227 if (prevPacket
!= null || fLive
) {
234 * If an event is available, read it.
236 if (fPacketReader
.hasMoreEvents()) {
237 setCurrentEvent(fPacketReader
.readNextEvent());
238 return CTFResponse
.OK
;
240 this.setCurrentEvent(null);
241 return fLive ? CTFResponse
.WAIT
: CTFResponse
.FINISH
;
245 * Change the current packet of the packet reader to the next one.
247 * @throws CTFReaderException
250 private void goToNextPacket() throws CTFReaderException
{
252 // did we already index the packet?
253 if (getPacketSize() >= (fPacketIndex
+ 1)) {
254 fPacketReader
.setCurrentPacket(getPacket());
256 // go to the next packet if there is one, index it at the same time
257 if (fStreamInput
.addPacketHeaderIndex()) {
258 fPacketIndex
= getPacketSize() - 1;
259 fPacketReader
.setCurrentPacket(getPacket());
262 fPacketReader
.setCurrentPacket(null);
270 private int getPacketSize() {
271 return fStreamInput
.getIndex().getEntries().size();
275 * Changes the location of the trace file reader so that the current event
276 * is the first event with a timestamp greater or equal the given timestamp.
279 * The timestamp to seek to.
280 * @return The offset compared to the current position
281 * @throws CTFReaderException
284 public long seek(long timestamp
) throws CTFReaderException
{
287 gotoPacket(timestamp
);
290 * index up to the desired timestamp.
292 while ((fPacketReader
.getCurrentPacket() != null)
293 && (fPacketReader
.getCurrentPacket().getTimestampEnd() < timestamp
)) {
295 fStreamInput
.addPacketHeaderIndex();
297 } catch (CTFReaderException e
) {
301 if (fPacketReader
.getCurrentPacket() == null) {
302 gotoPacket(timestamp
);
306 * Advance until either of these conditions are met:
308 * - reached the end of the trace file (the given timestamp is after the
311 * - found the first event with a timestamp greater or equal the given
315 boolean done
= (this.getCurrentEvent() == null);
316 while (!done
&& (this.getCurrentEvent().getTimestamp() < timestamp
)) {
318 done
= (this.getCurrentEvent() == null);
327 * @throws CTFReaderException
330 private void gotoPacket(long timestamp
) throws CTFReaderException
{
331 fPacketIndex
= fStreamInput
.getIndex().search(timestamp
)
334 * Switch to this packet.
340 * Seeks the last event of a stream and returns it.
342 * @throws CTFReaderException
345 public void goToLastEvent() throws CTFReaderException
{
347 * Search in the index for the packet to search in.
349 final int len
= fStreamInput
.getIndex().getEntries().size();
352 * Go to beginning of trace.
356 * if the trace is empty.
358 if ((len
== 0) || (fPacketReader
.hasMoreEvents() == false)) {
360 * This means the trace is empty. abort.
365 * Go to the last packet that contains events.
367 for (int pos
= len
- 1; pos
> 0; pos
--) {
369 fPacketReader
.setCurrentPacket(getPacket());
370 if (fPacketReader
.hasMoreEvents()) {
376 * Go until the end of that packet
378 EventDefinition prevEvent
= null;
379 while (fCurrentEvent
!= null) {
380 prevEvent
= fCurrentEvent
;
381 this.readNextEvent();
384 * Go back to the previous event
386 this.setCurrentEvent(prevEvent
);
392 public CTFTraceReader
getParent() {
400 public void setParent(CTFTraceReader parent
) {
405 * Sets the current event in a stream input reader
407 * @param currentEvent
410 public void setCurrentEvent(EventDefinition currentEvent
) {
411 fCurrentEvent
= currentEvent
;
415 * @return the packetIndexIt
417 private int getPacketIndex() {
421 private StreamInputPacketIndexEntry
getPacket() {
422 return fStreamInput
.getIndex().getEntries().get(getPacketIndex());
426 * @return the packetReader
428 public CTFStreamInputPacketReader
getPacketReader() {
429 return fPacketReader
;
433 public int hashCode() {
434 final int prime
= 31;
436 result
= (prime
* result
) + fId
;
437 result
= (prime
* result
)
438 + fStreamInput
.hashCode();
443 public boolean equals(Object obj
) {
450 if (!(obj
instanceof CTFStreamInputReader
)) {
453 CTFStreamInputReader other
= (CTFStreamInputReader
) obj
;
454 if (fId
!= other
.fId
) {
457 return fStreamInput
.equals(other
.fStreamInput
);
461 public String
toString() {
462 // this helps debugging
463 return fId
+ ' ' + fCurrentEvent
.toString();