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