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 * <b><u>StreamInputPacketReader</u></b>
36 * Reads the events of a packet of a trace file.
38 public class StreamInputPacketReader
implements IDefinitionScope
{
40 // ------------------------------------------------------------------------
42 // ------------------------------------------------------------------------
45 * Reference to the index entry of the current packet.
47 private StreamInputPacketIndexEntry currentPacket
= null;
50 * BitBuffer used to read the trace file.
52 private final BitBuffer bitBuffer
= new BitBuffer();
55 * StreamInputReader that uses this StreamInputPacketReader.
57 private final StreamInputReader streamInputReader
;
60 * Last timestamp recorded.
62 * Needed to calculate the complete timestamp values for the events with
65 private long lastTimestamp
= 0;
68 * Trace packet header.
70 private StructDefinition tracePacketHeaderDef
= null;
73 * Stream packet context definition.
75 private StructDefinition streamPacketContextDef
= null;
78 * Stream event header definition.
80 private StructDefinition streamEventHeaderDef
= null;
83 * Stream event context definition.
85 private StructDefinition streamEventContextDef
= null;
88 * Maps event ID to event definitions.
90 private final HashMap
<Long
, EventDefinition
> events
;
93 * CPU id of current packet.
95 private int currentCpu
= 0;
98 * number of lost events in this packet
100 private int lostEvents
;
102 private int lostSoFar
;
104 // ------------------------------------------------------------------------
106 // ------------------------------------------------------------------------
109 * Constructs a StreamInputPacketReader.
111 * @param streamInputReader
112 * The StreamInputReader to which this packet reader belongs to.
114 public StreamInputPacketReader(StreamInputReader streamInputReader
) {
115 this.streamInputReader
= streamInputReader
;
118 * Set the BitBuffer's byte order.
120 getBitBuffer().setByteOrder(streamInputReader
.getByteOrder());
122 events
= streamInputReader
.getStreamInput().getStream().getTrace()
123 .getEventDefs(streamInputReader
.getStreamInput());
125 * Create definitions needed to read the events.
133 // ------------------------------------------------------------------------
135 // ------------------------------------------------------------------------
137 // ------------------------------------------------------------------------
138 // Getters/Setters/Predicates
139 // ------------------------------------------------------------------------
141 /* Getters, setters and stuff. */
143 public StreamInputPacketIndexEntry
getCurrentPacket() {
144 return this.currentPacket
;
147 public StructDefinition
getStreamPacketContextDef() {
148 return this.streamPacketContextDef
;
151 public int getCPU() {
152 return this.currentCpu
;
156 public String
getPath() {
157 return ""; //$NON-NLS-1$
160 // ------------------------------------------------------------------------
162 // ------------------------------------------------------------------------
165 * Creates definitions needed to read events (stream-defined and
168 private void createDefinitions() {
170 * Create trace packet header definition.
172 final Stream currentStream
= getStreamInputReader().getStreamInput()
174 StructDeclaration tracePacketHeaderDecl
= currentStream
.getTrace()
176 if (tracePacketHeaderDecl
!= null) {
177 setTracePacketHeaderDef(tracePacketHeaderDecl
.createDefinition(
178 this, "trace.packet.header")); //$NON-NLS-1$
182 * Create stream packet context definition.
184 StructDeclaration streamPacketContextDecl
= currentStream
185 .getPacketContextDecl();
186 if (streamPacketContextDecl
!= null) {
187 setStreamPacketContextDef(streamPacketContextDecl
.createDefinition(
188 this, "stream.packet.context")); //$NON-NLS-1$
192 * Create stream event header definition.
194 StructDeclaration streamEventHeaderDecl
= currentStream
195 .getEventHeaderDecl();
196 if (streamEventHeaderDecl
!= null) {
197 setStreamEventHeaderDef(streamEventHeaderDecl
.createDefinition(
198 this, "stream.event.header")); //$NON-NLS-1$
202 * Create stream event context definition.
204 StructDeclaration streamEventContextDecl
= currentStream
205 .getEventContextDecl();
206 if (streamEventContextDecl
!= null) {
207 setStreamEventContextDef(streamEventContextDecl
.createDefinition(
208 this, "stream.event.context")); //$NON-NLS-1$
211 createEventDefinitions();
215 * Creates definitions needed to read the event. (event-defined).
217 private void createEventDefinitions() {
218 Collection
<EventDeclaration
> eventDecls
= getStreamInputReader()
219 .getStreamInput().getStream().getEvents().values();
222 * Create definitions for each event.
224 for (EventDeclaration event
: eventDecls
) {
225 if (!events
.containsKey(event
.getId())) {
226 EventDefinition eventDef
= event
227 .createDefinition(getStreamInputReader());
228 events
.put(event
.getId(), eventDef
);
234 * Changes the current packet to the given one.
236 * @param currentPacket
237 * The index entry of the packet to switch to.
239 public void setCurrentPacket(StreamInputPacketIndexEntry currentPacket
) {
240 this.currentPacket
= currentPacket
;
242 if (this.currentPacket
!= null) {
244 * Change the map of the BitBuffer.
246 MappedByteBuffer bb
= null;
248 bb
= getStreamInputReader()
251 .map(MapMode
.READ_ONLY
,
252 this.currentPacket
.getOffsetBytes(),
253 (this.currentPacket
.getPacketSizeBits() + 7) / 8);
254 } catch (IOException e
) {
256 * The streamInputReader object is already allocated, so this
257 * shouldn't fail bar some very bad kernel or RAM errors...
262 getBitBuffer().setByteBuffer(bb
);
265 * Read trace packet header.
267 if (getTracePacketHeaderDef() != null) {
268 getTracePacketHeaderDef().read(getBitBuffer());
272 * Read stream packet context.
274 if (getStreamPacketContextDef() != null) {
275 getStreamPacketContextDef().read(getBitBuffer());
280 Definition cpuiddef
= getStreamPacketContextDef()
281 .lookupDefinition("cpu_id"); //$NON-NLS-1$
282 if (cpuiddef
instanceof IntegerDefinition
) {
283 currentCpu
= (int) ((IntegerDefinition
) cpuiddef
)
287 * Read number of lost events
289 Definition lostEventsdef
= getStreamPacketContextDef()
290 .lookupDefinition("events_discarded"); //$NON-NLS-1$
291 if (cpuiddef
instanceof IntegerDefinition
) {
292 lostEvents
= (int) ((IntegerDefinition
) lostEventsdef
)
299 * Use the timestamp begin of the packet as the reference for the
300 * timestamp reconstitution.
302 lastTimestamp
= currentPacket
.getTimestampBegin();
304 getBitBuffer().setByteBuffer(null);
311 * Returns whether it is possible to read any more events from this packet.
313 * @return True if it is possible to read any more events from this packet.
315 public boolean hasMoreEvents() {
316 if (currentPacket
!= null) {
317 return getBitBuffer().position() < currentPacket
318 .getContentSizeBits();
324 * Reads the next event of the packet into the right event definition.
326 * @return The event definition containing the event data that was just
328 * @throws CTFReaderException
330 public EventDefinition
readNextEvent() throws CTFReaderException
{
331 /* WARNING: This is very LTTng-specific. */
335 if (lostEvents
> lostSoFar
) {
336 EventDefinition eventDef
= EventDeclaration
337 .getLostEventDeclaration().createDefinition(
339 eventDef
.setTimestamp(this.lastTimestamp
);
343 StructDefinition sehd
= getStreamEventHeaderDef(); // acronym for a long
345 BitBuffer currentBitBuffer
= getBitBuffer();
347 * Read the stream event header.
351 sehd
.read(currentBitBuffer
);
354 * Check for an event id.
356 EnumDefinition idEnumDef
= (EnumDefinition
) sehd
357 .lookupDefinition("id"); //$NON-NLS-1$
358 assert (idEnumDef
!= null);
360 eventID
= idEnumDef
.getIntegerValue();
363 * Check for the variant v.
365 VariantDefinition variantDef
= (VariantDefinition
) sehd
366 .lookupDefinition("v"); //$NON-NLS-1$
367 assert (variantDef
!= null);
370 * Get the variant current field
372 StructDefinition variantCurrentField
= (StructDefinition
) variantDef
374 assert (variantCurrentField
!= null);
377 * Try to get the id field in the current field of the variant. If
378 * it is present, it overrides the previously read event id.
380 IntegerDefinition idIntegerDef
= (IntegerDefinition
) variantCurrentField
381 .lookupDefinition("id"); //$NON-NLS-1$
382 if (idIntegerDef
!= null) {
383 eventID
= idIntegerDef
.getValue();
389 IntegerDefinition timestampDef
= (IntegerDefinition
) variantCurrentField
390 .lookupDefinition("timestamp"); //$NON-NLS-1$
391 assert (timestampDef
!= null);
394 * Calculate the event timestamp.
396 timestamp
= calculateTimestamp(timestampDef
);
400 * Read the stream event context.
402 if (getStreamEventContextDef() != null) {
403 getStreamEventContextDef().read(currentBitBuffer
);
407 * Get the right event definition using the event id.
409 EventDefinition eventDef
= events
.get(eventID
);
410 if (eventDef
== null) {
411 throw new CTFReaderException("Incorrect event id : " + eventID
); //$NON-NLS-1$
415 * Read the event context.
417 if (eventDef
.getContext() != null) {
418 eventDef
.getContext().read(currentBitBuffer
);
422 * Read the event fields.
424 if (eventDef
.getFields() != null) {
425 eventDef
.getFields().read(currentBitBuffer
);
429 * Set the event timestamp using the timestamp calculated by
432 eventDef
.setTimestamp(timestamp
);
438 * Calculates the timestamp value of the event, possibly using the timestamp
439 * from the last event.
441 * @param timestampDef
442 * Integer definition of the timestamp.
443 * @return The calculated timestamp value.
445 private long calculateTimestamp(IntegerDefinition timestampDef
) {
448 int len
= timestampDef
.getDeclaration().getLength();
451 * If the timestamp length is 64 bits, it is a full timestamp.
453 if (timestampDef
.getDeclaration().getLength() == 64) {
454 lastTimestamp
= timestampDef
.getValue();
455 return lastTimestamp
;
459 * Bit mask to keep / remove all old / new bits.
461 majorasbitmask
= (1L << len
) - 1;
464 * If the new value is smaller than the corresponding bits of the last
465 * timestamp, we assume an overflow of the compact representation.
467 newval
= timestampDef
.getValue();
468 if (newval
< (lastTimestamp
& majorasbitmask
)) {
469 newval
= newval
+ (1L << len
);
472 /* Keep only the high bits of the old value */
473 lastTimestamp
= lastTimestamp
& ~majorasbitmask
;
475 /* Then add the low bits of the new value */
476 lastTimestamp
= lastTimestamp
+ newval
;
478 return lastTimestamp
;
481 @SuppressWarnings("unused")
483 public Definition
lookupDefinition(String lookupPath
) {
484 // TODO Auto-generated method stub
488 public StructDefinition
getStreamEventContextDef() {
489 return this.streamEventContextDef
;
492 public void setStreamEventContextDef(StructDefinition streamEventContextDef
) {
493 this.streamEventContextDef
= streamEventContextDef
;
496 public StructDefinition
getStreamEventHeaderDef() {
497 return this.streamEventHeaderDef
;
500 public void setStreamEventHeaderDef(StructDefinition streamEventHeaderDef
) {
501 this.streamEventHeaderDef
= streamEventHeaderDef
;
504 public void setStreamPacketContextDef(
505 StructDefinition streamPacketContextDef
) {
506 this.streamPacketContextDef
= streamPacketContextDef
;
509 public StructDefinition
getTracePacketHeaderDef() {
510 return this.tracePacketHeaderDef
;
513 public void setTracePacketHeaderDef(StructDefinition tracePacketHeaderDef
) {
514 this.tracePacketHeaderDef
= tracePacketHeaderDef
;
517 public StreamInputReader
getStreamInputReader() {
518 return this.streamInputReader
;
521 public BitBuffer
getBitBuffer() {