Fix lost events to work after multiple reloads
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / StreamInputPacketReader.java
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 *******************************************************************************/
12 package org.eclipse.linuxtools.ctf.core.trace;
13
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;
19
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;
32
33 /**
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
39 */
40 public class StreamInputPacketReader implements IDefinitionScope {
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 */
92 private final HashMap<Long, EventDefinition> events;
93
94 /**
95 * CPU id of current packet.
96 */
97 private int currentCpu = 0;
98
99 /**
100 * number of lost events in this packet
101 */
102 private int lostEvents;
103
104 private int lostSoFar;
105
106 private int lostEventsInThisPacket;
107
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 */
124 getBitBuffer().setByteOrder(streamInputReader.getByteOrder());
125
126 events = streamInputReader.getStreamInput().getStream().getTrace()
127 .getEventDefs(streamInputReader.getStreamInput());
128 /*
129 * Create definitions needed to read the events.
130 */
131 createDefinitions();
132
133 lostEvents = 0;
134 lostSoFar = 0;
135 }
136
137 // ------------------------------------------------------------------------
138 // Constructors
139 // ------------------------------------------------------------------------
140
141 // ------------------------------------------------------------------------
142 // Getters/Setters/Predicates
143 // ------------------------------------------------------------------------
144
145 /**
146 * Gets the current packet
147 *
148 * @return the current packet
149 */
150 public StreamInputPacketIndexEntry getCurrentPacket() {
151 return this.currentPacket;
152 }
153
154 /**
155 * Gets the steamPacketContext Definition
156 *
157 * @return steamPacketContext Definition
158 */
159 public StructDefinition getStreamPacketContextDef() {
160 return this.streamPacketContextDef;
161 }
162
163 /**
164 * Gets the CPU (core) number
165 *
166 * @return the CPU (core) number
167 */
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 */
189 final Stream currentStream = getStreamInputReader().getStreamInput()
190 .getStream();
191 StructDeclaration tracePacketHeaderDecl = currentStream.getTrace()
192 .getPacketHeader();
193 if (tracePacketHeaderDecl != null) {
194 setTracePacketHeaderDef(tracePacketHeaderDecl.createDefinition(
195 this, "trace.packet.header")); //$NON-NLS-1$
196 }
197
198 /*
199 * Create stream packet context definition.
200 */
201 StructDeclaration streamPacketContextDecl = currentStream
202 .getPacketContextDecl();
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 */
211 StructDeclaration streamEventHeaderDecl = currentStream
212 .getEventHeaderDecl();
213 if (streamEventHeaderDecl != null) {
214 setStreamEventHeaderDef(streamEventHeaderDecl.createDefinition(
215 this, "stream.event.header")); //$NON-NLS-1$
216 }
217
218 /*
219 * Create stream event context definition.
220 */
221 StructDeclaration streamEventContextDecl = currentStream
222 .getEventContextDecl();
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() {
235 Collection<EventDeclaration> eventDecls = getStreamInputReader()
236 .getStreamInput().getStream().getEvents().values();
237
238 /*
239 * Create definitions for each event.
240 */
241 for (EventDeclaration event : eventDecls) {
242 if (!events.containsKey(event.getId())) {
243 EventDefinition eventDef = event
244 .createDefinition(getStreamInputReader());
245 events.put(event.getId(), eventDef);
246 }
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 {
265 bb = getStreamInputReader()
266 .getStreamInput()
267 .getFileChannel()
268 .map(MapMode.READ_ONLY,
269 this.currentPacket.getOffsetBytes(),
270 (this.currentPacket.getPacketSizeBits() + 7) / 8);
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());
293 /*
294 * Read CPU ID
295 */
296
297 Definition cpuiddef = getStreamPacketContextDef()
298 .lookupDefinition("cpu_id"); //$NON-NLS-1$
299 if (cpuiddef instanceof IntegerDefinition) {
300 currentCpu = (int) ((IntegerDefinition) cpuiddef)
301 .getValue();
302 }
303 /*
304 * Read number of lost events
305 */
306 Definition lostEventsdef = getStreamPacketContextDef()
307 .lookupDefinition("events_discarded"); //$NON-NLS-1$
308 if (cpuiddef instanceof IntegerDefinition) {
309 int totalLostEvents = (int) ((IntegerDefinition) lostEventsdef)
310 .getValue();
311 lostEventsInThisPacket = totalLostEvents - lostEvents;
312 lostEvents = totalLostEvents;
313 currentPacket.setLostEvents(lostEventsInThisPacket);
314 lostSoFar = 0;
315 }
316 }
317
318 /*
319 * Use the timestamp begin of the packet as the reference for the
320 * timestamp reconstitution.
321 */
322 lastTimestamp = currentPacket.getTimestampBegin();
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) {
337 return getBitBuffer().position() < currentPacket
338 .getContentSizeBits();
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
349 * If there was a problem reading the trace
350 */
351 public EventDefinition readNextEvent() throws CTFReaderException {
352 /* WARNING: This is very LTTng-specific. */
353 Long eventID = null;
354 long timestamp = 0;
355
356 if (lostEventsInThisPacket > lostSoFar) {
357 EventDefinition eventDef = EventDeclaration
358 .getLostEventDeclaration().createDefinition(
359 streamInputReader);
360 eventDef.setTimestamp(this.lastTimestamp);
361 ++lostSoFar;
362 return eventDef;
363 }
364 StructDefinition sehd = getStreamEventHeaderDef(); // acronym for a long
365 // variable name
366 BitBuffer currentBitBuffer = getBitBuffer();
367 /*
368 * Read the stream event header.
369 */
370
371 if (sehd != null) {
372 sehd.read(currentBitBuffer);
373
374 /*
375 * Check for an event id.
376 */
377 EnumDefinition idEnumDef = (EnumDefinition) sehd
378 .lookupDefinition("id"); //$NON-NLS-1$
379 assert (idEnumDef != null);
380
381 eventID = idEnumDef.getIntegerValue();
382
383 /*
384 * Check for the variant v.
385 */
386 VariantDefinition variantDef = (VariantDefinition) sehd
387 .lookupDefinition("v"); //$NON-NLS-1$
388 assert (variantDef != null);
389
390 /*
391 * Get the variant current field
392 */
393 StructDefinition variantCurrentField = (StructDefinition) variantDef
394 .getCurrentField();
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 */
401 IntegerDefinition idIntegerDef = (IntegerDefinition) variantCurrentField
402 .lookupDefinition("id"); //$NON-NLS-1$
403 if (idIntegerDef != null) {
404 eventID = idIntegerDef.getValue();
405 }
406
407 /*
408 * Get the timestamp.
409 */
410 IntegerDefinition timestampDef = (IntegerDefinition) variantCurrentField
411 .lookupDefinition("timestamp"); //$NON-NLS-1$
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) {
424 getStreamEventContextDef().read(currentBitBuffer);
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 */
438 if (eventDef.getContext() != null) {
439 eventDef.getContext().read(currentBitBuffer);
440 }
441
442 /*
443 * Read the event fields.
444 */
445 if (eventDef.getFields() != null) {
446 eventDef.getFields().read(currentBitBuffer);
447 }
448
449 /*
450 * Set the event timestamp using the timestamp calculated by
451 * updateTimestamp.
452 */
453 eventDef.setTimestamp(timestamp);
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
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 */
514 public StructDefinition getStreamEventContextDef() {
515 return this.streamEventContextDef;
516 }
517
518 /**
519 * Sets the stream event context definition
520 *
521 * @param streamEventContextDef
522 * The stream event context definition
523 */
524 public void setStreamEventContextDef(StructDefinition streamEventContextDef) {
525 this.streamEventContextDef = streamEventContextDef;
526 }
527
528 /**
529 * Gets the stream event header definition
530 *
531 * @return the stream event header definition
532 */
533 public StructDefinition getStreamEventHeaderDef() {
534 return this.streamEventHeaderDef;
535 }
536
537 /**
538 * Sets the stream event header definition
539 *
540 * @param streamEventHeaderDef
541 * the stream event header definition
542 */
543 public void setStreamEventHeaderDef(StructDefinition streamEventHeaderDef) {
544 this.streamEventHeaderDef = streamEventHeaderDef;
545 }
546
547 /**
548 * Sets the stream packet context definition
549 *
550 * @param streamPacketContextDef
551 * the stream packet context definition
552 */
553 public void setStreamPacketContextDef(
554 StructDefinition streamPacketContextDef) {
555 this.streamPacketContextDef = streamPacketContextDef;
556 }
557
558 /**
559 * Gets the trace packet header definition
560 *
561 * @return the trace packet header definition
562 */
563 public StructDefinition getTracePacketHeaderDef() {
564 return this.tracePacketHeaderDef;
565 }
566
567 /**
568 * Sets the trace packet header definition
569 *
570 * @param tracePacketHeaderDef
571 * the trace packet header definition
572 */
573 public void setTracePacketHeaderDef(StructDefinition tracePacketHeaderDef) {
574 this.tracePacketHeaderDef = tracePacketHeaderDef;
575 }
576
577 /**
578 * @return the parent stream input reader
579 */
580 public StreamInputReader getStreamInputReader() {
581 return this.streamInputReader;
582 }
583
584 /**
585 *
586 * @return THe bit buffer that reads the file.
587 */
588 public BitBuffer getBitBuffer() {
589 return bitBuffer;
590 }
591 }
This page took 0.05529 seconds and 5 git commands to generate.