Fix issues with CTF parser.
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / StreamInputPacketReader.java
CommitLineData
866e5b51
FC
1/*******************************************************************************
2 * Copyright (c) 2011-2012 Ericsson, Ecole Polytechnique de Montreal and others
3 *
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
8 *
9 * Contributors: Matthew Khouzam - Initial API and implementation
10 * Contributors: Simon Marchi - Initial API and implementation
11 *******************************************************************************/
12package org.eclipse.linuxtools.ctf.core.trace;
13
14import java.io.IOException;
15import java.nio.MappedByteBuffer;
16import java.nio.channels.FileChannel.MapMode;
17import java.util.Collection;
18import java.util.HashMap;
19
20import org.eclipse.linuxtools.ctf.core.event.EventDeclaration;
21import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
866e5b51
FC
22import org.eclipse.linuxtools.ctf.core.event.types.Definition;
23import org.eclipse.linuxtools.ctf.core.event.types.EnumDefinition;
24import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
25import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
26import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
27import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
28import org.eclipse.linuxtools.ctf.core.event.types.VariantDefinition;
ce2388e0
FC
29import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
30import org.eclipse.linuxtools.internal.ctf.core.trace.Stream;
31import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
866e5b51
FC
32
33/**
d37aaa7f 34 * CTF trace packet reader. Reads the events of a packet of a trace file.
5c7202b5 35 *
d37aaa7f
FC
36 * @version 1.0
37 * @author Matthew Khouzam
38 * @author Simon Marchi
866e5b51 39 */
bfe038ff 40public class StreamInputPacketReader implements IDefinitionScope {
866e5b51
FC
41
42 // ------------------------------------------------------------------------
43 // Constants
44 // ------------------------------------------------------------------------
45
46 /**
47 * Reference to the index entry of the current packet.
48 */
49 private StreamInputPacketIndexEntry currentPacket = null;
50
51 /**
52 * BitBuffer used to read the trace file.
53 */
54 private final BitBuffer bitBuffer = new BitBuffer();
55
56 /**
57 * StreamInputReader that uses this StreamInputPacketReader.
58 */
59 private final StreamInputReader streamInputReader;
60
61 /**
62 * Last timestamp recorded.
63 *
64 * Needed to calculate the complete timestamp values for the events with
65 * compact headers.
66 */
67 private long lastTimestamp = 0;
68
69 /**
70 * Trace packet header.
71 */
72 private StructDefinition tracePacketHeaderDef = null;
73
74 /**
75 * Stream packet context definition.
76 */
77 private StructDefinition streamPacketContextDef = null;
78
79 /**
80 * Stream event header definition.
81 */
82 private StructDefinition streamEventHeaderDef = null;
83
84 /**
85 * Stream event context definition.
86 */
87 private StructDefinition streamEventContextDef = null;
88
89 /**
90 * Maps event ID to event definitions.
91 */
788ddcbc 92 private final HashMap<Long, EventDefinition> events;
866e5b51
FC
93
94 /**
95 * CPU id of current packet.
96 */
97 private int currentCpu = 0;
98
33656d8e
MK
99 /**
100 * number of lost events in this packet
101 */
102 private int lostEvents;
103
104 private int lostSoFar;
105
5c7202b5
MK
106 private int lostEventsInThisPacket;
107
866e5b51
FC
108 // ------------------------------------------------------------------------
109 // Attributes
110 // ------------------------------------------------------------------------
111
112 /**
113 * Constructs a StreamInputPacketReader.
114 *
115 * @param streamInputReader
116 * The StreamInputReader to which this packet reader belongs to.
117 */
118 public StreamInputPacketReader(StreamInputReader streamInputReader) {
119 this.streamInputReader = streamInputReader;
120
121 /*
122 * Set the BitBuffer's byte order.
123 */
ce2388e0 124 getBitBuffer().setByteOrder(streamInputReader.getByteOrder());
866e5b51 125
788ddcbc
MK
126 events = streamInputReader.getStreamInput().getStream().getTrace()
127 .getEventDefs(streamInputReader.getStreamInput());
866e5b51
FC
128 /*
129 * Create definitions needed to read the events.
130 */
131 createDefinitions();
33656d8e 132
788ddcbc
MK
133 lostEvents = 0;
134 lostSoFar = 0;
866e5b51
FC
135 }
136
137 // ------------------------------------------------------------------------
138 // Constructors
139 // ------------------------------------------------------------------------
140
141 // ------------------------------------------------------------------------
142 // Getters/Setters/Predicates
143 // ------------------------------------------------------------------------
144
9ac2eb62
MK
145 /**
146 * Gets the current packet
147 *
148 * @return the current packet
149 */
866e5b51
FC
150 public StreamInputPacketIndexEntry getCurrentPacket() {
151 return this.currentPacket;
152 }
153
9ac2eb62
MK
154 /**
155 * Gets the steamPacketContext Definition
156 *
157 * @return steamPacketContext Definition
158 */
866e5b51
FC
159 public StructDefinition getStreamPacketContextDef() {
160 return this.streamPacketContextDef;
161 }
162
9ac2eb62
MK
163 /**
164 * Gets the CPU (core) number
165 *
166 * @return the CPU (core) number
167 */
866e5b51
FC
168 public int getCPU() {
169 return this.currentCpu;
170 }
171
172 @Override
173 public String getPath() {
174 return ""; //$NON-NLS-1$
175 }
176
177 // ------------------------------------------------------------------------
178 // Operations
179 // ------------------------------------------------------------------------
180
181 /**
182 * Creates definitions needed to read events (stream-defined and
183 * event-defined).
184 */
185 private void createDefinitions() {
186 /*
187 * Create trace packet header definition.
188 */
788ddcbc
MK
189 final Stream currentStream = getStreamInputReader().getStreamInput()
190 .getStream();
191 StructDeclaration tracePacketHeaderDecl = currentStream.getTrace()
192 .getPacketHeader();
866e5b51 193 if (tracePacketHeaderDecl != null) {
788ddcbc
MK
194 setTracePacketHeaderDef(tracePacketHeaderDecl.createDefinition(
195 this, "trace.packet.header")); //$NON-NLS-1$
866e5b51
FC
196 }
197
198 /*
199 * Create stream packet context definition.
200 */
788ddcbc
MK
201 StructDeclaration streamPacketContextDecl = currentStream
202 .getPacketContextDecl();
866e5b51
FC
203 if (streamPacketContextDecl != null) {
204 setStreamPacketContextDef(streamPacketContextDecl.createDefinition(
205 this, "stream.packet.context")); //$NON-NLS-1$
206 }
207
208 /*
209 * Create stream event header definition.
210 */
788ddcbc
MK
211 StructDeclaration streamEventHeaderDecl = currentStream
212 .getEventHeaderDecl();
866e5b51 213 if (streamEventHeaderDecl != null) {
788ddcbc
MK
214 setStreamEventHeaderDef(streamEventHeaderDecl.createDefinition(
215 this, "stream.event.header")); //$NON-NLS-1$
866e5b51
FC
216 }
217
218 /*
219 * Create stream event context definition.
220 */
788ddcbc
MK
221 StructDeclaration streamEventContextDecl = currentStream
222 .getEventContextDecl();
866e5b51
FC
223 if (streamEventContextDecl != null) {
224 setStreamEventContextDef(streamEventContextDecl.createDefinition(
225 this, "stream.event.context")); //$NON-NLS-1$
226 }
227
228 createEventDefinitions();
229 }
230
231 /**
232 * Creates definitions needed to read the event. (event-defined).
233 */
234 private void createEventDefinitions() {
788ddcbc
MK
235 Collection<EventDeclaration> eventDecls = getStreamInputReader()
236 .getStreamInput().getStream().getEvents().values();
866e5b51
FC
237
238 /*
239 * Create definitions for each event.
240 */
241 for (EventDeclaration event : eventDecls) {
788ddcbc
MK
242 if (!events.containsKey(event.getId())) {
243 EventDefinition eventDef = event
244 .createDefinition(getStreamInputReader());
245 events.put(event.getId(), eventDef);
246 }
866e5b51
FC
247 }
248 }
249
250 /**
251 * Changes the current packet to the given one.
252 *
253 * @param currentPacket
254 * The index entry of the packet to switch to.
255 */
256 public void setCurrentPacket(StreamInputPacketIndexEntry currentPacket) {
257 this.currentPacket = currentPacket;
258
259 if (this.currentPacket != null) {
260 /*
261 * Change the map of the BitBuffer.
262 */
263 MappedByteBuffer bb = null;
264 try {
788ddcbc
MK
265 bb = getStreamInputReader()
266 .getStreamInput()
267 .getFileChannel()
268 .map(MapMode.READ_ONLY,
269 this.currentPacket.getOffsetBytes(),
270 (this.currentPacket.getPacketSizeBits() + 7) / 8);
866e5b51
FC
271 } catch (IOException e) {
272 /*
273 * The streamInputReader object is already allocated, so this
274 * shouldn't fail bar some very bad kernel or RAM errors...
275 */
276 e.printStackTrace();
277 }
278
279 getBitBuffer().setByteBuffer(bb);
280
281 /*
282 * Read trace packet header.
283 */
284 if (getTracePacketHeaderDef() != null) {
285 getTracePacketHeaderDef().read(getBitBuffer());
286 }
287
288 /*
289 * Read stream packet context.
290 */
291 if (getStreamPacketContextDef() != null) {
292 getStreamPacketContextDef().read(getBitBuffer());
33656d8e
MK
293 /*
294 * Read CPU ID
295 */
296
788ddcbc
MK
297 Definition cpuiddef = getStreamPacketContextDef()
298 .lookupDefinition("cpu_id"); //$NON-NLS-1$
866e5b51 299 if (cpuiddef instanceof IntegerDefinition) {
788ddcbc
MK
300 currentCpu = (int) ((IntegerDefinition) cpuiddef)
301 .getValue();
866e5b51 302 }
33656d8e
MK
303 /*
304 * Read number of lost events
305 */
788ddcbc
MK
306 Definition lostEventsdef = getStreamPacketContextDef()
307 .lookupDefinition("events_discarded"); //$NON-NLS-1$
33656d8e 308 if (cpuiddef instanceof IntegerDefinition) {
5c7202b5 309 int totalLostEvents = (int) ((IntegerDefinition) lostEventsdef)
788ddcbc 310 .getValue();
5c7202b5
MK
311 lostEventsInThisPacket = totalLostEvents - lostEvents;
312 lostEvents = totalLostEvents;
313 currentPacket.setLostEvents(lostEventsInThisPacket);
314 lostSoFar = 0;
33656d8e 315 }
866e5b51
FC
316 }
317
318 /*
319 * Use the timestamp begin of the packet as the reference for the
320 * timestamp reconstitution.
321 */
ce2388e0 322 lastTimestamp = currentPacket.getTimestampBegin();
866e5b51
FC
323 } else {
324 getBitBuffer().setByteBuffer(null);
325
326 lastTimestamp = 0;
327 }
328 }
329
330 /**
331 * Returns whether it is possible to read any more events from this packet.
332 *
333 * @return True if it is possible to read any more events from this packet.
334 */
335 public boolean hasMoreEvents() {
336 if (currentPacket != null) {
788ddcbc
MK
337 return getBitBuffer().position() < currentPacket
338 .getContentSizeBits();
866e5b51
FC
339 }
340 return false;
341 }
342
343 /**
344 * Reads the next event of the packet into the right event definition.
345 *
346 * @return The event definition containing the event data that was just
347 * read.
348 * @throws CTFReaderException
be6df2d8 349 * If there was a problem reading the trace
866e5b51
FC
350 */
351 public EventDefinition readNextEvent() throws CTFReaderException {
352 /* WARNING: This is very LTTng-specific. */
866e5b51
FC
353 Long eventID = null;
354 long timestamp = 0;
355
5c7202b5 356 if (lostEventsInThisPacket > lostSoFar) {
788ddcbc
MK
357 EventDefinition eventDef = EventDeclaration
358 .getLostEventDeclaration().createDefinition(
359 streamInputReader);
aa572e22 360 eventDef.setTimestamp(this.lastTimestamp);
33656d8e
MK
361 ++lostSoFar;
362 return eventDef;
363 }
788ddcbc
MK
364 StructDefinition sehd = getStreamEventHeaderDef(); // acronym for a long
365 // variable name
2b7f6f09 366 BitBuffer currentBitBuffer = getBitBuffer();
866e5b51 367 /*
fd74e6c1 368 * Read the stream event header.
866e5b51 369 */
2b7f6f09
MK
370
371 if (sehd != null) {
372 sehd.read(currentBitBuffer);
866e5b51
FC
373
374 /*
375 * Check for an event id.
376 */
788ddcbc
MK
377 EnumDefinition idEnumDef = (EnumDefinition) sehd
378 .lookupDefinition("id"); //$NON-NLS-1$
866e5b51
FC
379 assert (idEnumDef != null);
380
381 eventID = idEnumDef.getIntegerValue();
382
383 /*
384 * Check for the variant v.
385 */
788ddcbc
MK
386 VariantDefinition variantDef = (VariantDefinition) sehd
387 .lookupDefinition("v"); //$NON-NLS-1$
866e5b51
FC
388 assert (variantDef != null);
389
390 /*
391 * Get the variant current field
392 */
788ddcbc
MK
393 StructDefinition variantCurrentField = (StructDefinition) variantDef
394 .getCurrentField();
866e5b51
FC
395 assert (variantCurrentField != null);
396
397 /*
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.
400 */
788ddcbc
MK
401 IntegerDefinition idIntegerDef = (IntegerDefinition) variantCurrentField
402 .lookupDefinition("id"); //$NON-NLS-1$
866e5b51
FC
403 if (idIntegerDef != null) {
404 eventID = idIntegerDef.getValue();
866e5b51
FC
405 }
406
407 /*
408 * Get the timestamp.
409 */
788ddcbc
MK
410 IntegerDefinition timestampDef = (IntegerDefinition) variantCurrentField
411 .lookupDefinition("timestamp"); //$NON-NLS-1$
866e5b51
FC
412 assert (timestampDef != null);
413
414 /*
415 * Calculate the event timestamp.
416 */
417 timestamp = calculateTimestamp(timestampDef);
418 }
419
420 /*
421 * Read the stream event context.
422 */
423 if (getStreamEventContextDef() != null) {
2b7f6f09 424 getStreamEventContextDef().read(currentBitBuffer);
866e5b51
FC
425 }
426
427 /*
428 * Get the right event definition using the event id.
429 */
430 EventDefinition eventDef = events.get(eventID);
431 if (eventDef == null) {
432 throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
433 }
434
435 /*
436 * Read the event context.
437 */
aa572e22
MK
438 if (eventDef.getContext() != null) {
439 eventDef.getContext().read(currentBitBuffer);
866e5b51
FC
440 }
441
442 /*
443 * Read the event fields.
444 */
aa572e22
MK
445 if (eventDef.getFields() != null) {
446 eventDef.getFields().read(currentBitBuffer);
866e5b51
FC
447 }
448
449 /*
450 * Set the event timestamp using the timestamp calculated by
451 * updateTimestamp.
452 */
aa572e22 453 eventDef.setTimestamp(timestamp);
866e5b51
FC
454
455 return eventDef;
456 }
457
458 /**
459 * Calculates the timestamp value of the event, possibly using the timestamp
460 * from the last event.
461 *
462 * @param timestampDef
463 * Integer definition of the timestamp.
464 * @return The calculated timestamp value.
465 */
466 private long calculateTimestamp(IntegerDefinition timestampDef) {
467 long newval;
468 long majorasbitmask;
469 int len = timestampDef.getDeclaration().getLength();
470
471 /*
472 * If the timestamp length is 64 bits, it is a full timestamp.
473 */
474 if (timestampDef.getDeclaration().getLength() == 64) {
475 lastTimestamp = timestampDef.getValue();
476 return lastTimestamp;
477 }
478
479 /*
480 * Bit mask to keep / remove all old / new bits.
481 */
482 majorasbitmask = (1L << len) - 1;
483
484 /*
485 * If the new value is smaller than the corresponding bits of the last
486 * timestamp, we assume an overflow of the compact representation.
487 */
488 newval = timestampDef.getValue();
489 if (newval < (lastTimestamp & majorasbitmask)) {
490 newval = newval + (1L << len);
491 }
492
493 /* Keep only the high bits of the old value */
494 lastTimestamp = lastTimestamp & ~majorasbitmask;
495
496 /* Then add the low bits of the new value */
497 lastTimestamp = lastTimestamp + newval;
498
499 return lastTimestamp;
500 }
501
502 @Override
503 public Definition lookupDefinition(String lookupPath) {
504 // TODO Auto-generated method stub
505 return null;
506 }
507
9ac2eb62
MK
508 /**
509 * Gets the stream event context definition (see CTF specs)
510 *
511 * @return the definition of the stream event context (the form not the
512 * content)
513 */
866e5b51
FC
514 public StructDefinition getStreamEventContextDef() {
515 return this.streamEventContextDef;
516 }
517
9ac2eb62
MK
518 /**
519 * Sets the stream event context definition
520 *
521 * @param streamEventContextDef
522 * The stream event context definition
523 */
866e5b51
FC
524 public void setStreamEventContextDef(StructDefinition streamEventContextDef) {
525 this.streamEventContextDef = streamEventContextDef;
526 }
527
9ac2eb62
MK
528 /**
529 * Gets the stream event header definition
530 *
531 * @return the stream event header definition
532 */
866e5b51
FC
533 public StructDefinition getStreamEventHeaderDef() {
534 return this.streamEventHeaderDef;
535 }
536
9ac2eb62
MK
537 /**
538 * Sets the stream event header definition
539 *
540 * @param streamEventHeaderDef
541 * the stream event header definition
542 */
866e5b51
FC
543 public void setStreamEventHeaderDef(StructDefinition streamEventHeaderDef) {
544 this.streamEventHeaderDef = streamEventHeaderDef;
545 }
546
9ac2eb62
MK
547 /**
548 * Sets the stream packet context definition
549 *
550 * @param streamPacketContextDef
551 * the stream packet context definition
552 */
788ddcbc
MK
553 public void setStreamPacketContextDef(
554 StructDefinition streamPacketContextDef) {
866e5b51
FC
555 this.streamPacketContextDef = streamPacketContextDef;
556 }
557
9ac2eb62
MK
558 /**
559 * Gets the trace packet header definition
560 *
561 * @return the trace packet header definition
562 */
866e5b51
FC
563 public StructDefinition getTracePacketHeaderDef() {
564 return this.tracePacketHeaderDef;
565 }
566
9ac2eb62
MK
567 /**
568 * Sets the trace packet header definition
569 *
570 * @param tracePacketHeaderDef
571 * the trace packet header definition
572 */
866e5b51
FC
573 public void setTracePacketHeaderDef(StructDefinition tracePacketHeaderDef) {
574 this.tracePacketHeaderDef = tracePacketHeaderDef;
575 }
576
9ac2eb62
MK
577 /**
578 * @return the parent stream input reader
579 */
866e5b51
FC
580 public StreamInputReader getStreamInputReader() {
581 return this.streamInputReader;
582 }
583
9ac2eb62
MK
584 /**
585 *
586 * @return THe bit buffer that reads the file.
587 */
866e5b51
FC
588 public BitBuffer getBitBuffer() {
589 return bitBuffer;
590 }
591}
This page took 0.06759 seconds and 5 git commands to generate.