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