1 /*******************************************************************************
2 * Copyright (c) 2011-2012 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 *******************************************************************************/
12 package org
.eclipse
.linuxtools
.ctf
.core
.trace
;
14 import java
.io
.IOException
;
15 import java
.nio
.MappedByteBuffer
;
16 import java
.nio
.channels
.FileChannel
.MapMode
;
17 import java
.util
.Collection
;
18 import java
.util
.HashMap
;
20 import org
.eclipse
.linuxtools
.ctf
.core
.event
.EventDeclaration
;
21 import org
.eclipse
.linuxtools
.ctf
.core
.event
.EventDefinition
;
22 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.Definition
;
23 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.EnumDefinition
;
24 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IDefinitionScope
;
25 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.IntegerDefinition
;
26 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDeclaration
;
27 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.StructDefinition
;
28 import org
.eclipse
.linuxtools
.ctf
.core
.event
.types
.VariantDefinition
;
29 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.event
.io
.BitBuffer
;
30 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.trace
.Stream
;
31 import org
.eclipse
.linuxtools
.internal
.ctf
.core
.trace
.StreamInputPacketIndexEntry
;
34 * CTF trace packet reader. Reads the events of a packet of a trace file.
37 * @author Matthew Khouzam
38 * @author Simon Marchi
40 public class StreamInputPacketReader
implements IDefinitionScope
{
42 // ------------------------------------------------------------------------
44 // ------------------------------------------------------------------------
47 * Reference to the index entry of the current packet.
49 private StreamInputPacketIndexEntry currentPacket
= null;
52 * BitBuffer used to read the trace file.
54 private final BitBuffer bitBuffer
= new BitBuffer();
57 * StreamInputReader that uses this StreamInputPacketReader.
59 private final StreamInputReader streamInputReader
;
62 * Last timestamp recorded.
64 * Needed to calculate the complete timestamp values for the events with
67 private long lastTimestamp
= 0;
70 * Trace packet header.
72 private StructDefinition tracePacketHeaderDef
= null;
75 * Stream packet context definition.
77 private StructDefinition streamPacketContextDef
= null;
80 * Stream event header definition.
82 private StructDefinition streamEventHeaderDef
= null;
85 * Stream event context definition.
87 private StructDefinition streamEventContextDef
= null;
90 * Maps event ID to event definitions.
92 private final HashMap
<Long
, EventDefinition
> events
;
95 * CPU id of current packet.
97 private int currentCpu
= 0;
100 * number of lost events in this packet
102 private int lostEvents
;
104 private int lostSoFar
;
106 private int lostEventsInThisPacket
;
108 // ------------------------------------------------------------------------
110 // ------------------------------------------------------------------------
113 * Constructs a StreamInputPacketReader.
115 * @param streamInputReader
116 * The StreamInputReader to which this packet reader belongs to.
118 public StreamInputPacketReader(StreamInputReader streamInputReader
) {
119 this.streamInputReader
= streamInputReader
;
122 * Set the BitBuffer's byte order.
124 getBitBuffer().setByteOrder(streamInputReader
.getByteOrder());
126 events
= streamInputReader
.getStreamInput().getStream().getTrace()
127 .getEventDefs(streamInputReader
.getStreamInput());
129 * Create definitions needed to read the events.
137 // ------------------------------------------------------------------------
139 // ------------------------------------------------------------------------
141 // ------------------------------------------------------------------------
142 // Getters/Setters/Predicates
143 // ------------------------------------------------------------------------
146 * Gets the current packet
148 * @return the current packet
150 public StreamInputPacketIndexEntry
getCurrentPacket() {
151 return this.currentPacket
;
155 * Gets the steamPacketContext Definition
157 * @return steamPacketContext Definition
159 public StructDefinition
getStreamPacketContextDef() {
160 return this.streamPacketContextDef
;
164 * Gets the CPU (core) number
166 * @return the CPU (core) number
168 public int getCPU() {
169 return this.currentCpu
;
173 public String
getPath() {
174 return ""; //$NON-NLS-1$
177 // ------------------------------------------------------------------------
179 // ------------------------------------------------------------------------
182 * Creates definitions needed to read events (stream-defined and
185 private void createDefinitions() {
187 * Create trace packet header definition.
189 final Stream currentStream
= getStreamInputReader().getStreamInput()
191 StructDeclaration tracePacketHeaderDecl
= currentStream
.getTrace()
193 if (tracePacketHeaderDecl
!= null) {
194 setTracePacketHeaderDef(tracePacketHeaderDecl
.createDefinition(
195 this, "trace.packet.header")); //$NON-NLS-1$
199 * Create stream packet context definition.
201 StructDeclaration streamPacketContextDecl
= currentStream
202 .getPacketContextDecl();
203 if (streamPacketContextDecl
!= null) {
204 setStreamPacketContextDef(streamPacketContextDecl
.createDefinition(
205 this, "stream.packet.context")); //$NON-NLS-1$
209 * Create stream event header definition.
211 StructDeclaration streamEventHeaderDecl
= currentStream
212 .getEventHeaderDecl();
213 if (streamEventHeaderDecl
!= null) {
214 setStreamEventHeaderDef(streamEventHeaderDecl
.createDefinition(
215 this, "stream.event.header")); //$NON-NLS-1$
219 * Create stream event context definition.
221 StructDeclaration streamEventContextDecl
= currentStream
222 .getEventContextDecl();
223 if (streamEventContextDecl
!= null) {
224 setStreamEventContextDef(streamEventContextDecl
.createDefinition(
225 this, "stream.event.context")); //$NON-NLS-1$
228 createEventDefinitions();
232 * Creates definitions needed to read the event. (event-defined).
234 private void createEventDefinitions() {
235 Collection
<EventDeclaration
> eventDecls
= getStreamInputReader()
236 .getStreamInput().getStream().getEvents().values();
239 * Create definitions for each event.
241 for (EventDeclaration event
: eventDecls
) {
242 if (!events
.containsKey(event
.getId())) {
243 EventDefinition eventDef
= event
244 .createDefinition(getStreamInputReader());
245 events
.put(event
.getId(), eventDef
);
251 * Changes the current packet to the given one.
253 * @param currentPacket
254 * The index entry of the packet to switch to.
256 public void setCurrentPacket(StreamInputPacketIndexEntry currentPacket
) {
257 this.currentPacket
= currentPacket
;
259 if (this.currentPacket
!= null) {
261 * Change the map of the BitBuffer.
263 MappedByteBuffer bb
= null;
265 bb
= getStreamInputReader()
268 .map(MapMode
.READ_ONLY
,
269 this.currentPacket
.getOffsetBytes(),
270 (this.currentPacket
.getPacketSizeBits() + 7) / 8);
271 } catch (IOException e
) {
273 * The streamInputReader object is already allocated, so this
274 * shouldn't fail bar some very bad kernel or RAM errors...
279 getBitBuffer().setByteBuffer(bb
);
282 * Read trace packet header.
284 if (getTracePacketHeaderDef() != null) {
285 getTracePacketHeaderDef().read(getBitBuffer());
289 * Read stream packet context.
291 if (getStreamPacketContextDef() != null) {
292 getStreamPacketContextDef().read(getBitBuffer());
297 Definition cpuiddef
= getStreamPacketContextDef()
298 .lookupDefinition("cpu_id"); //$NON-NLS-1$
299 if (cpuiddef
instanceof IntegerDefinition
) {
300 currentCpu
= (int) ((IntegerDefinition
) cpuiddef
)
304 * Read number of lost events
306 Definition lostEventsdef
= getStreamPacketContextDef()
307 .lookupDefinition("events_discarded"); //$NON-NLS-1$
308 if (cpuiddef
instanceof IntegerDefinition
) {
309 int totalLostEvents
= (int) ((IntegerDefinition
) lostEventsdef
)
311 lostEventsInThisPacket
= totalLostEvents
- lostEvents
;
312 lostEvents
= totalLostEvents
;
313 currentPacket
.setLostEvents(lostEventsInThisPacket
);
319 * Use the timestamp begin of the packet as the reference for the
320 * timestamp reconstitution.
322 lastTimestamp
= currentPacket
.getTimestampBegin();
324 getBitBuffer().setByteBuffer(null);
331 * Returns whether it is possible to read any more events from this packet.
333 * @return True if it is possible to read any more events from this packet.
335 public boolean hasMoreEvents() {
336 if (currentPacket
!= null) {
337 return getBitBuffer().position() < currentPacket
338 .getContentSizeBits();
344 * Reads the next event of the packet into the right event definition.
346 * @return The event definition containing the event data that was just
348 * @throws CTFReaderException
349 * If there was a problem reading the trace
351 public EventDefinition
readNextEvent() throws CTFReaderException
{
352 /* WARNING: This is very LTTng-specific. */
356 if (lostEventsInThisPacket
> lostSoFar
) {
357 EventDefinition eventDef
= EventDeclaration
358 .getLostEventDeclaration().createDefinition(
360 eventDef
.setTimestamp(this.lastTimestamp
);
364 StructDefinition sehd
= getStreamEventHeaderDef(); // acronym for a long
366 BitBuffer currentBitBuffer
= getBitBuffer();
368 * Read the stream event header.
372 sehd
.read(currentBitBuffer
);
375 * Check for an event id.
377 EnumDefinition idEnumDef
= (EnumDefinition
) sehd
378 .lookupDefinition("id"); //$NON-NLS-1$
379 assert (idEnumDef
!= null);
381 eventID
= idEnumDef
.getIntegerValue();
384 * Check for the variant v.
386 VariantDefinition variantDef
= (VariantDefinition
) sehd
387 .lookupDefinition("v"); //$NON-NLS-1$
388 assert (variantDef
!= null);
391 * Get the variant current field
393 StructDefinition variantCurrentField
= (StructDefinition
) variantDef
395 assert (variantCurrentField
!= null);
398 * Try to get the id field in the current field of the variant. If
399 * it is present, it overrides the previously read event id.
401 IntegerDefinition idIntegerDef
= (IntegerDefinition
) variantCurrentField
402 .lookupDefinition("id"); //$NON-NLS-1$
403 if (idIntegerDef
!= null) {
404 eventID
= idIntegerDef
.getValue();
410 IntegerDefinition timestampDef
= (IntegerDefinition
) variantCurrentField
411 .lookupDefinition("timestamp"); //$NON-NLS-1$
412 assert (timestampDef
!= null);
415 * Calculate the event timestamp.
417 timestamp
= calculateTimestamp(timestampDef
);
421 * Read the stream event context.
423 if (getStreamEventContextDef() != null) {
424 getStreamEventContextDef().read(currentBitBuffer
);
428 * Get the right event definition using the event id.
430 EventDefinition eventDef
= events
.get(eventID
);
431 if (eventDef
== null) {
432 throw new CTFReaderException("Incorrect event id : " + eventID
); //$NON-NLS-1$
436 * Read the event context.
438 if (eventDef
.getContext() != null) {
439 eventDef
.getContext().read(currentBitBuffer
);
443 * Read the event fields.
445 if (eventDef
.getFields() != null) {
446 eventDef
.getFields().read(currentBitBuffer
);
450 * Set the event timestamp using the timestamp calculated by
453 eventDef
.setTimestamp(timestamp
);
459 * Calculates the timestamp value of the event, possibly using the timestamp
460 * from the last event.
462 * @param timestampDef
463 * Integer definition of the timestamp.
464 * @return The calculated timestamp value.
466 private long calculateTimestamp(IntegerDefinition timestampDef
) {
469 int len
= timestampDef
.getDeclaration().getLength();
472 * If the timestamp length is 64 bits, it is a full timestamp.
474 if (timestampDef
.getDeclaration().getLength() == 64) {
475 lastTimestamp
= timestampDef
.getValue();
476 return lastTimestamp
;
480 * Bit mask to keep / remove all old / new bits.
482 majorasbitmask
= (1L << len
) - 1;
485 * If the new value is smaller than the corresponding bits of the last
486 * timestamp, we assume an overflow of the compact representation.
488 newval
= timestampDef
.getValue();
489 if (newval
< (lastTimestamp
& majorasbitmask
)) {
490 newval
= newval
+ (1L << len
);
493 /* Keep only the high bits of the old value */
494 lastTimestamp
= lastTimestamp
& ~majorasbitmask
;
496 /* Then add the low bits of the new value */
497 lastTimestamp
= lastTimestamp
+ newval
;
499 return lastTimestamp
;
503 public Definition
lookupDefinition(String lookupPath
) {
504 // TODO Auto-generated method stub
509 * Gets the stream event context definition (see CTF specs)
511 * @return the definition of the stream event context (the form not the
514 public StructDefinition
getStreamEventContextDef() {
515 return this.streamEventContextDef
;
519 * Sets the stream event context definition
521 * @param streamEventContextDef
522 * The stream event context definition
524 public void setStreamEventContextDef(StructDefinition streamEventContextDef
) {
525 this.streamEventContextDef
= streamEventContextDef
;
529 * Gets the stream event header definition
531 * @return the stream event header definition
533 public StructDefinition
getStreamEventHeaderDef() {
534 return this.streamEventHeaderDef
;
538 * Sets the stream event header definition
540 * @param streamEventHeaderDef
541 * the stream event header definition
543 public void setStreamEventHeaderDef(StructDefinition streamEventHeaderDef
) {
544 this.streamEventHeaderDef
= streamEventHeaderDef
;
548 * Sets the stream packet context definition
550 * @param streamPacketContextDef
551 * the stream packet context definition
553 public void setStreamPacketContextDef(
554 StructDefinition streamPacketContextDef
) {
555 this.streamPacketContextDef
= streamPacketContextDef
;
559 * Gets the trace packet header definition
561 * @return the trace packet header definition
563 public StructDefinition
getTracePacketHeaderDef() {
564 return this.tracePacketHeaderDef
;
568 * Sets the trace packet header definition
570 * @param tracePacketHeaderDef
571 * the trace packet header definition
573 public void setTracePacketHeaderDef(StructDefinition tracePacketHeaderDef
) {
574 this.tracePacketHeaderDef
= tracePacketHeaderDef
;
578 * @return the parent stream input reader
580 public StreamInputReader
getStreamInputReader() {
581 return this.streamInputReader
;
586 * @return THe bit buffer that reads the file.
588 public BitBuffer
getBitBuffer() {