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
.Activator
;
23 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.trace
.StreamInputPacketIndexEntry
;
26 * A CTF trace event reader. Reads the events of a trace file.
29 * @author Matthew Khouzam
30 * @author Simon Marchi
32 public class StreamInputReader
{
34 // ------------------------------------------------------------------------
36 // ------------------------------------------------------------------------
39 * The StreamInput we are reading.
41 private final StreamInput streamInput
;
44 * The packet reader used to read packets from this trace file.
46 private final StreamInputPacketReader packetReader
;
49 * Iterator on the packet index
51 private int packetIndex
;
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 currentEvent
= null;
61 private CTFTraceReader parent
;
63 /** Map of all the event types */
64 private final Map
<Long
, EventDefinition
> eventDefs
= new HashMap
<Long
, EventDefinition
>();
66 // ------------------------------------------------------------------------
68 // ------------------------------------------------------------------------
71 * Constructs a StreamInputReader that reads a StreamInput.
74 * The StreamInput to read.
75 * @throws CTFReaderException
79 public StreamInputReader(StreamInput streamInput
) throws CTFReaderException
{
80 this.streamInput
= streamInput
;
81 this.packetReader
= new StreamInputPacketReader(this);
83 * Get the iterator on the packet index.
87 * Make first packet the current one.
93 * Dispose the StreamInputReader
97 public void dispose() {
98 packetReader
.dispose();
101 // ------------------------------------------------------------------------
102 // Getters/Setters/Predicates
103 // ------------------------------------------------------------------------
106 * Gets the current event in this stream
108 * @return the current event in the stream, null if the stream is
109 * finished/empty/malformed
111 public EventDefinition
getCurrentEvent() {
112 return this.currentEvent
;
116 * Gets the current packet context
118 * @return the current packet context (size, lost events and such)
120 public StructDefinition
getCurrentPacketContext() {
121 return this.packetReader
.getStreamPacketContextDef();
125 * Gets the byte order for a trace
127 * @return the trace byte order
129 public ByteOrder
getByteOrder() {
130 return streamInput
.getStream().getTrace().getByteOrder();
134 * Gets the name of the stream (it's an id and a number)
136 * @return gets the stream name (it's a number)
138 public int getName() {
143 * Sets the name of the stream
146 * the name of the stream, (it's a number)
148 public void setName(int name
) {
153 * Gets the CPU of a stream. It's the same as the one in /proc or running
154 * the asm CPUID instruction
156 * @return The CPU id (a number)
158 public int getCPU() {
159 return this.packetReader
.getCPU();
163 * Gets the filename of the stream being read
165 * @return The filename of the stream being read
167 public String
getFilename() {
168 return streamInput
.getFilename();
172 * for internal use only
174 StreamInput
getStreamInput() {
179 * Gets the event definition hashmap for this StreamInput
181 * @return Unmodifiable map with the event definitions
184 public Map
<Long
, EventDefinition
> getEventDefinitions() {
185 return Collections
.unmodifiableMap(eventDefs
);
189 * Add an event definition to this stream input reader.
192 * The id of the event definition. This will overwrite any
193 * existing definition with the same id.
195 * The matching event definition
198 public void addEventDefinition(Long id
, EventDefinition def
) {
199 eventDefs
.put(id
, def
);
202 // ------------------------------------------------------------------------
204 // ------------------------------------------------------------------------
206 * Reads the next event in the current event variable.
208 * @return If an event has been successfully read.
209 * @throws CTFReaderException
212 public boolean readNextEvent() throws CTFReaderException
{
215 * Change packet if needed
217 if (!this.packetReader
.hasMoreEvents()) {
218 final StreamInputPacketIndexEntry prevPacket
= this.packetReader
220 if (prevPacket
!= null) {
226 * If an event is available, read it.
228 if (this.packetReader
.hasMoreEvents()) {
230 this.setCurrentEvent(this.packetReader
.readNextEvent());
231 } catch (CTFReaderException e
) {
233 * Some problem happened, we'll assume that there are no more
236 Activator
.logError("Error reading CTF event in stream", e
); //$NON-NLS-1$
241 this.setCurrentEvent(null);
246 * Change the current packet of the packet reader to the next one.
248 * @throws CTFReaderException
251 private void goToNextPacket() throws CTFReaderException
{
253 if (getPacketSize() >= (packetIndex
+ 1)) {
254 this.packetReader
.setCurrentPacket(getPacket());
257 if (this.streamInput
.addPacketHeaderIndex()) {
258 packetIndex
= getPacketSize() - 1;
259 this.packetReader
.setCurrentPacket(getPacket());
261 this.packetReader
.setCurrentPacket(null);
264 } catch (CTFReaderException e
) {
265 this.packetReader
.setCurrentPacket(null);
273 private int getPacketSize() {
274 return streamInput
.getIndex().getEntries().size();
278 * Changes the location of the trace file reader so that the current event
279 * is the first event with a timestamp greater or equal the given timestamp.
282 * The timestamp to seek to.
283 * @return The offset compared to the current position
284 * @throws CTFReaderException
287 public long seek(long timestamp
) throws CTFReaderException
{
290 gotoPacket(timestamp
);
293 * index up to the desired timestamp.
295 while ((this.packetReader
.getCurrentPacket() != null)
296 && (this.packetReader
.getCurrentPacket().getTimestampEnd() < timestamp
)) {
298 this.streamInput
.addPacketHeaderIndex();
300 } catch (CTFReaderException e
) {
304 if (this.packetReader
.getCurrentPacket() == null) {
305 gotoPacket(timestamp
);
309 * Advance until either of these conditions are met
311 * <li> reached the end of the trace file (the given timestamp is after the last event), </li>
312 * <li> found the first event with a timestamp greater or equal the given timestamp. </li>
316 boolean done
= (this.getCurrentEvent() == null);
317 while (!done
&& (this.getCurrentEvent().getTimestamp() < timestamp
)) {
319 done
= (this.getCurrentEvent() == null);
327 * @throws CTFReaderException
330 private void gotoPacket(long timestamp
) throws CTFReaderException
{
331 this.packetIndex
= this.streamInput
.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
= this.streamInput
.getIndex().getEntries().size();
352 * Go to beginning of trace.
356 * if the trace is empty.
358 if ((len
== 0) || (this.packetReader
.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 this.packetReader
.setCurrentPacket(getPacket());
370 if (this.packetReader
.hasMoreEvents()) {
376 * Go until the end of that packet
378 EventDefinition prevEvent
= null;
379 while (this.currentEvent
!= null) {
380 prevEvent
= this.currentEvent
;
381 this.readNextEvent();
384 * Go back to the previous event
386 this.setCurrentEvent(prevEvent
);
392 public CTFTraceReader
getParent() {
400 public void setParent(CTFTraceReader parent
) {
401 this.parent
= parent
;
405 * Sets the current event in a stream input reader
407 * @param currentEvent
410 public void setCurrentEvent(EventDefinition currentEvent
) {
411 this.currentEvent
= currentEvent
;
415 * @return the packetIndexIt
417 private int getPacketIndex() {
421 private StreamInputPacketIndexEntry
getPacket() {
422 return streamInput
.getIndex().getEntries().get(getPacketIndex());
426 * @return the packetReader
428 public StreamInputPacketReader
getPacketReader() {
433 public int hashCode() {
434 final int prime
= 31;
436 result
= (prime
* result
) + name
;
437 result
= (prime
* result
)
438 + ((streamInput
== null) ?
0 : streamInput
.hashCode());
443 public boolean equals(Object obj
) {
450 if (!(obj
instanceof StreamInputReader
)) {
453 StreamInputReader other
= (StreamInputReader
) obj
;
454 if (name
!= other
.name
) {
457 if (streamInput
== null) {
458 if (other
.streamInput
!= null) {
461 } else if (!streamInput
.equals(other
.streamInput
)) {
468 public String
toString() {
469 // this helps debugging
470 return this.name
+ ' ' + this.currentEvent
.toString();