[CTF] Events wrongly parsed as Lost Events
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / ctf / core / trace / CTFStreamInputPacketReader.java
CommitLineData
866e5b51 1/*******************************************************************************
74d58b9b 2 * Copyright (c) 2011, 2015 Ericsson, Ecole Polytechnique de Montreal and others
866e5b51
FC
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 *
74d58b9b
PT
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
11 * Simon Marchi - Initial API and implementation
12 * Patrick Tasse - Bug 470754 - Incorrect time range in CTF Lost Event
866e5b51 13 *******************************************************************************/
f357bcd4 14package org.eclipse.tracecompass.ctf.core.trace;
866e5b51
FC
15
16import java.io.IOException;
526c823c 17import java.nio.ByteBuffer;
b3151232 18import java.nio.channels.FileChannel.MapMode;
866e5b51 19
a4fa4e36 20import org.eclipse.jdt.annotation.NonNull;
733c614c 21import org.eclipse.jdt.annotation.Nullable;
680f9173 22import org.eclipse.tracecompass.ctf.core.CTFException;
f357bcd4
AM
23import org.eclipse.tracecompass.ctf.core.CTFStrings;
24import org.eclipse.tracecompass.ctf.core.event.EventDefinition;
25import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
a433ce7d 26import org.eclipse.tracecompass.ctf.core.event.LostEventDeclaration;
f357bcd4
AM
27import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
28import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope;
fbe6fa6f 29import org.eclipse.tracecompass.ctf.core.event.scope.ILexicalScope;
f357bcd4
AM
30import org.eclipse.tracecompass.ctf.core.event.scope.LexicalScope;
31import org.eclipse.tracecompass.ctf.core.event.types.Definition;
32import org.eclipse.tracecompass.ctf.core.event.types.ICompositeDefinition;
33import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
34import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
35import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
36import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
37import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
38import org.eclipse.tracecompass.ctf.core.event.types.SimpleDatatypeDefinition;
39import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
40import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
41import org.eclipse.tracecompass.ctf.core.event.types.VariantDefinition;
42import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer;
94c255ef 43import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
f357bcd4 44import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition;
866e5b51
FC
45
46/**
d37aaa7f 47 * CTF trace packet reader. Reads the events of a packet of a trace file.
5c7202b5 48 *
d37aaa7f
FC
49 * @author Matthew Khouzam
50 * @author Simon Marchi
866e5b51 51 */
d84419e1 52public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseable {
866e5b51
FC
53
54 // ------------------------------------------------------------------------
6bdc9fac 55 // Attributes
866e5b51
FC
56 // ------------------------------------------------------------------------
57
f068c622
MK
58 private static final int BITS_PER_BYTE = Byte.SIZE;
59
94c255ef
MK
60 private static final IDefinitionScope EVENT_HEADER_SCOPE = new IDefinitionScope() {
61
62 @Override
63 public IDefinition lookupDefinition(String lookupPath) {
64 return null;
65 }
66
67 @Override
68 public ILexicalScope getScopePath() {
69 return null;
70 }
71 };
72
6bdc9fac 73 /** BitBuffer used to read the trace file. */
733c614c
MK
74 @Nullable
75 private BitBuffer fBitBuffer;
866e5b51 76
6bdc9fac 77 /** StreamInputReader that uses this StreamInputPacketReader. */
d84419e1 78 private final CTFStreamInputReader fStreamInputReader;
866e5b51 79
6bdc9fac 80 /** Trace packet header. */
a4fa4e36 81 private final StructDeclaration fTracePacketHeaderDecl;
866e5b51 82
6bdc9fac 83 /** Stream packet context definition. */
a4fa4e36 84 private final StructDeclaration fStreamPacketContextDecl;
866e5b51 85
6bdc9fac 86 /** Stream event header definition. */
6c7592e1 87 private final IDeclaration fStreamEventHeaderDecl;
866e5b51 88
c26d0fe0 89 /** Stream event context definition. */
a4fa4e36 90 private final StructDeclaration fStreamEventContextDecl;
866e5b51 91
6c7592e1
MK
92 private ICompositeDefinition fCurrentTracePacketHeaderDef;
93 private ICompositeDefinition fCurrentStreamEventHeaderDef;
94 private ICompositeDefinition fCurrentStreamPacketContextDef;
6bdc9fac 95 /** Reference to the index entry of the current packet. */
1d92f045 96 private ICTFPacketDescriptor fCurrentPacket = null;
6bdc9fac 97
866e5b51 98 /**
6bdc9fac
AM
99 * Last timestamp recorded.
100 *
101 * Needed to calculate the complete timestamp values for the events with
102 * compact headers.
866e5b51 103 */
2882273c 104 private long fLastTimestamp = 0;
6bdc9fac
AM
105
106 /** CPU id of current packet. */
2882273c 107 private int fCurrentCpu = 0;
866e5b51 108
2882273c 109 private int fLostEventsInThisPacket;
5c7202b5 110
2882273c 111 private boolean fHasLost = false;
c26d0fe0 112
866e5b51 113 // ------------------------------------------------------------------------
6bdc9fac 114 // Constructors
866e5b51
FC
115 // ------------------------------------------------------------------------
116
117 /**
118 * Constructs a StreamInputPacketReader.
119 *
120 * @param streamInputReader
121 * The StreamInputReader to which this packet reader belongs to.
122 */
d84419e1 123 public CTFStreamInputPacketReader(CTFStreamInputReader streamInputReader) {
2882273c 124 fStreamInputReader = streamInputReader;
866e5b51 125
6bdc9fac 126 /* Set the BitBuffer's byte order. */
6c7592e1
MK
127 ByteBuffer allocateDirect = ByteBuffer.allocateDirect(0);
128 if (allocateDirect == null) {
129 throw new IllegalStateException("Unable to allocate 0 bytes!"); //$NON-NLS-1$
130 }
131 fBitBuffer = new BitBuffer(allocateDirect);
33656d8e 132
d84419e1 133 final CTFStream currentStream = streamInputReader.getStreamInput().getStream();
a4fa4e36
MK
134 fTracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
135 fStreamPacketContextDecl = currentStream.getPacketContextDecl();
6c7592e1 136 fStreamEventHeaderDecl = currentStream.getEventHeaderDeclaration();
a4fa4e36
MK
137 fStreamEventContextDecl = currentStream.getEventContextDecl();
138 }
6bdc9fac 139
a4fa4e36
MK
140 /**
141 * Get the event context defintiion
142 *
143 * @param input
144 * the bitbuffer to read from
145 * @return an context definition, can be null
680f9173 146 * @throws CTFException
a4fa4e36 147 * out of bounds exception or such
a4fa4e36 148 */
680f9173 149 public StructDefinition getEventContextDefinition(@NonNull BitBuffer input) throws CTFException {
fbe6fa6f 150 return fStreamEventContextDecl.createDefinition(fStreamInputReader.getStreamInput(), ILexicalScope.STREAM_EVENT_CONTEXT, input);
a4fa4e36 151 }
6bdc9fac 152
a4fa4e36
MK
153 /**
154 * Get the packet context defintiion
155 *
156 * @param input
157 * the bitbuffer to read from
158 * @return an context definition, can be null
680f9173 159 * @throws CTFException
a4fa4e36 160 * out of bounds exception or such
a4fa4e36 161 */
680f9173 162 public StructDefinition getStreamPacketContextDefinition(@NonNull BitBuffer input) throws CTFException {
fbe6fa6f 163 return fStreamPacketContextDecl.createDefinition(fStreamInputReader.getStreamInput(), ILexicalScope.STREAM_PACKET_CONTEXT, input);
a4fa4e36 164 }
6bdc9fac 165
a4fa4e36
MK
166 /**
167 * Get the event header defintiion
168 *
169 * @param input
170 * the bitbuffer to read from
171 * @return an header definition, can be null
680f9173 172 * @throws CTFException
a4fa4e36 173 * out of bounds exception or such
a4fa4e36 174 */
680f9173 175 public StructDefinition getTracePacketHeaderDefinition(@NonNull BitBuffer input) throws CTFException {
fbe6fa6f 176 return fTracePacketHeaderDecl.createDefinition(fStreamInputReader.getStreamInput().getStream().getTrace(), ILexicalScope.TRACE_PACKET_HEADER, input);
6bdc9fac 177 }
866e5b51 178
5d1c6919
PT
179 /**
180 * Dispose the StreamInputPacketReader
5d1c6919 181 */
dd9752d5
AM
182 @Override
183 public void close() {
733c614c 184 fBitBuffer = null;
5d1c6919
PT
185 }
186
866e5b51
FC
187 // ------------------------------------------------------------------------
188 // Getters/Setters/Predicates
189 // ------------------------------------------------------------------------
190
9ac2eb62
MK
191 /**
192 * Gets the current packet
193 *
194 * @return the current packet
195 */
1d92f045 196 ICTFPacketDescriptor getCurrentPacket() {
2882273c 197 return fCurrentPacket;
866e5b51
FC
198 }
199
9ac2eb62
MK
200 /**
201 * Gets the CPU (core) number
202 *
203 * @return the CPU (core) number
204 */
866e5b51 205 public int getCPU() {
2882273c 206 return fCurrentCpu;
866e5b51
FC
207 }
208
209 @Override
a4fa4e36 210 public LexicalScope getScopePath() {
fbe6fa6f 211 return ILexicalScope.PACKET;
866e5b51
FC
212 }
213
214 // ------------------------------------------------------------------------
215 // Operations
216 // ------------------------------------------------------------------------
217
b3151232 218 @NonNull
680f9173 219 private ByteBuffer getByteBufferAt(long position, long size) throws CTFException, IOException {
f4a474e3 220 ByteBuffer map = SafeMappedByteBuffer.map(fStreamInputReader.getFc(), MapMode.READ_ONLY, position, size);
b3151232 221 if (map == null) {
680f9173 222 throw new CTFIOException("Failed to allocate mapped byte buffer"); //$NON-NLS-1$
b3151232
MK
223 }
224 return map;
225 }
f068c622 226
866e5b51
FC
227 /**
228 * Changes the current packet to the given one.
229 *
230 * @param currentPacket
231 * The index entry of the packet to switch to.
680f9173 232 * @throws CTFException
db8e8f7d 233 * If we get an error reading the packet
1d92f045 234 * @since 1.0
866e5b51 235 */
1d92f045 236 public void setCurrentPacket(ICTFPacketDescriptor currentPacket) throws CTFException {
2882273c 237 fCurrentPacket = currentPacket;
dd7f1879 238 fHasLost = false;
866e5b51 239
2882273c 240 if (fCurrentPacket != null) {
866e5b51
FC
241 /*
242 * Change the map of the BitBuffer.
243 */
526c823c 244 ByteBuffer bb = null;
866e5b51 245 try {
04f0148f 246 bb = getByteBufferAt(fCurrentPacket.getOffsetBytes(), (fCurrentPacket.getPacketSizeBits() + BITS_PER_BYTE - 1) / BITS_PER_BYTE);
866e5b51 247 } catch (IOException e) {
680f9173 248 throw new CTFIOException(e.getMessage(), e);
866e5b51
FC
249 }
250
733c614c
MK
251 BitBuffer bitBuffer = new BitBuffer(bb);
252 fBitBuffer = bitBuffer;
866e5b51
FC
253 /*
254 * Read trace packet header.
255 */
a4fa4e36 256 if (fTracePacketHeaderDecl != null) {
733c614c 257 fCurrentTracePacketHeaderDef = getTracePacketHeaderDefinition(bitBuffer);
866e5b51
FC
258 }
259
260 /*
261 * Read stream packet context.
262 */
a4fa4e36 263 if (fStreamPacketContextDecl != null) {
733c614c 264 fCurrentStreamPacketContextDef = getStreamPacketContextDefinition(bitBuffer);
33656d8e 265
132a02b0 266 /* Read CPU ID */
2882273c
MK
267 if (getCurrentPacket().getTarget() != null) {
268 fCurrentCpu = (int) getCurrentPacket().getTargetId();
866e5b51 269 }
21fb02fa 270
132a02b0 271 /* Read number of lost events */
2882273c
MK
272 fLostEventsInThisPacket = (int) getCurrentPacket().getLostEvents();
273 if (fLostEventsInThisPacket != 0) {
274 fHasLost = true;
c26d0fe0 275 }
866e5b51
FC
276 }
277
278 /*
279 * Use the timestamp begin of the packet as the reference for the
280 * timestamp reconstitution.
281 */
5b341dc8 282 fLastTimestamp = Math.max(currentPacket.getTimestampBegin(), 0);
866e5b51 283 } else {
733c614c 284 fBitBuffer = null;
2882273c 285 fLastTimestamp = 0;
866e5b51
FC
286 }
287 }
288
289 /**
290 * Returns whether it is possible to read any more events from this packet.
291 *
292 * @return True if it is possible to read any more events from this packet.
293 */
294 public boolean hasMoreEvents() {
733c614c 295 BitBuffer bitBuffer = fBitBuffer;
1d92f045 296 ICTFPacketDescriptor currentPacket = fCurrentPacket;
733c614c
MK
297 if (currentPacket != null && bitBuffer != null) {
298 return fHasLost || (bitBuffer.position() < currentPacket.getContentSizeBits());
866e5b51
FC
299 }
300 return false;
301 }
302
303 /**
304 * Reads the next event of the packet into the right event definition.
305 *
306 * @return The event definition containing the event data that was just
307 * read.
680f9173 308 * @throws CTFException
be6df2d8 309 * If there was a problem reading the trace
866e5b51 310 */
680f9173 311 public EventDefinition readNextEvent() throws CTFException {
1fbaecd1 312 /* Default values for those fields */
5f715709 313 // compromise since we cannot have 64 bit addressing of arrays yet.
a433ce7d 314 int eventID = (int) IEventDeclaration.UNSET_EVENT_ID;
74d58b9b
PT
315 final BitBuffer currentBitBuffer = fBitBuffer;
316 final ICTFPacketDescriptor currentPacket = fCurrentPacket;
317 if (currentBitBuffer == null || currentPacket == null) {
318 return null;
319 }
320 final long posStart = currentBitBuffer.position();
321 /*
322 * Return the Lost Event after all other events in this packet.
323 */
324 if (fHasLost && posStart >= currentPacket.getContentSizeBits()) {
2882273c 325 fHasLost = false;
a433ce7d 326 IEventDeclaration lostEventDeclaration = LostEventDeclaration.INSTANCE;
a4fa4e36
MK
327 StructDeclaration lostFields = lostEventDeclaration.getFields();
328 // this is a hard coded map, we know it's not null
2db699c2 329 IntegerDeclaration lostFieldsDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_FIELD);
a4fa4e36
MK
330 if (lostFieldsDecl == null)
331 {
332 throw new IllegalStateException("Lost events count not declared!"); //$NON-NLS-1$
333 }
2db699c2 334 IntegerDeclaration lostEventsDurationDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_DURATION);
a4fa4e36
MK
335 if (lostEventsDurationDecl == null) {
336 throw new IllegalStateException("Lost events duration not declared!"); //$NON-NLS-1$
337 }
74d58b9b
PT
338 long lostEventsTimestamp = fLastTimestamp;
339 long lostEventsDuration = currentPacket.getTimestampEnd() - lostEventsTimestamp;
340 IntegerDefinition lostDurationDef = new IntegerDefinition(lostFieldsDecl, null, CTFStrings.LOST_EVENTS_DURATION, lostEventsDuration);
a4fa4e36
MK
341 IntegerDefinition lostCountDef = new IntegerDefinition(lostEventsDurationDecl, null, CTFStrings.LOST_EVENTS_FIELD, fLostEventsInThisPacket);
342 IntegerDefinition[] fields = new IntegerDefinition[] { lostCountDef, lostDurationDef };
a4fa4e36
MK
343 return new EventDefinition(
344 lostEventDeclaration,
345 fStreamInputReader,
74d58b9b 346 lostEventsTimestamp,
a4fa4e36
MK
347 null,
348 null,
349 null,
350 new StructDefinition(
351 lostFields,
352 this, "fields", //$NON-NLS-1$
a4fa4e36
MK
353 fields
354 ));
355
33656d8e 356 }
132a02b0 357
1fbaecd1 358 /* Read the stream event header. */
a4fa4e36 359 if (fStreamEventHeaderDecl != null) {
6c7592e1 360 if (fStreamEventHeaderDecl instanceof IEventHeaderDeclaration) {
94c255ef 361 fCurrentStreamEventHeaderDef = (ICompositeDefinition) fStreamEventHeaderDecl.createDefinition(EVENT_HEADER_SCOPE, "", currentBitBuffer); //$NON-NLS-1$
6c7592e1
MK
362 EventHeaderDefinition ehd = (EventHeaderDefinition) fCurrentStreamEventHeaderDef;
363 eventID = ehd.getId();
6c7592e1 364 } else {
94c255ef 365 fCurrentStreamEventHeaderDef = ((StructDeclaration) fStreamEventHeaderDecl).createDefinition(EVENT_HEADER_SCOPE, ILexicalScope.EVENT_HEADER, currentBitBuffer);
6c7592e1
MK
366 StructDefinition StructEventHeaderDef = (StructDefinition) fCurrentStreamEventHeaderDef;
367 /* Check for the event id. */
368 IDefinition idDef = StructEventHeaderDef.lookupDefinition("id"); //$NON-NLS-1$
369 SimpleDatatypeDefinition simpleIdDef = null;
370 if (idDef instanceof SimpleDatatypeDefinition) {
371 simpleIdDef = ((SimpleDatatypeDefinition) idDef);
372 } else if (idDef != null) {
680f9173 373 throw new CTFIOException("Id defintion not an integer, enum or float definiton in event header."); //$NON-NLS-1$
6c7592e1 374 }
6c7592e1
MK
375 /* Check for the variant v. */
376 IDefinition variantDef = StructEventHeaderDef.lookupDefinition("v"); //$NON-NLS-1$
377 if (variantDef instanceof VariantDefinition) {
866e5b51 378
6c7592e1
MK
379 /* Get the variant current field */
380 StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
866e5b51 381
6c7592e1
MK
382 /*
383 * Try to get the id field in the current field of the
384 * variant. If it is present, it overrides the previously
385 * read event id.
386 */
387 IDefinition vIdDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
388 if (vIdDef instanceof IntegerDefinition) {
389 simpleIdDef = (SimpleDatatypeDefinition) vIdDef;
390 }
866e5b51 391
6bdc9fac 392 }
6c7592e1 393 if (simpleIdDef != null) {
5f715709 394 eventID = simpleIdDef.getIntegerValue().intValue();
6c7592e1 395 }
21fb02fa 396 }
866e5b51 397 }
1fbaecd1 398 /* Get the right event definition using the event id. */
94c255ef 399 EventDeclaration eventDeclaration = (EventDeclaration) fStreamInputReader.getStreamInput().getStream().getEventDeclaration(eventID);
a4fa4e36 400 if (eventDeclaration == null) {
680f9173 401 throw new CTFIOException("Incorrect event id : " + eventID); //$NON-NLS-1$
866e5b51 402 }
5b341dc8
MK
403 EventDefinition eventDef = eventDeclaration.createDefinition(fStreamInputReader, fCurrentStreamEventHeaderDef, currentBitBuffer, fLastTimestamp);
404 fLastTimestamp = eventDef.getTimestamp();
866e5b51
FC
405 /*
406 * Set the event timestamp using the timestamp calculated by
407 * updateTimestamp.
408 */
866e5b51 409
cf9a28da 410 if (posStart == currentBitBuffer.position()) {
680f9173 411 throw new CTFIOException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$
cf9a28da
MK
412 }
413
866e5b51
FC
414 return eventDef;
415 }
416
866e5b51
FC
417 @Override
418 public Definition lookupDefinition(String lookupPath) {
fbe6fa6f 419 if (lookupPath.equals(ILexicalScope.STREAM_PACKET_CONTEXT.getPath())) {
6c7592e1 420 return (Definition) fCurrentStreamPacketContextDef;
a4fa4e36 421 }
fbe6fa6f 422 if (lookupPath.equals(ILexicalScope.TRACE_PACKET_HEADER.getPath())) {
6c7592e1 423 return (Definition) fCurrentTracePacketHeaderDef;
a4fa4e36 424 }
866e5b51
FC
425 return null;
426 }
a4fa4e36 427
6c7592e1
MK
428
429 /**
430 * Get stream event header
431 *
432 * @return the stream event header
6c7592e1
MK
433 */
434 public ICompositeDefinition getStreamEventHeaderDefinition() {
a4fa4e36
MK
435 return fCurrentStreamEventHeaderDef;
436 }
437
438 /**
439 * Get the current packet event header
440 *
441 * @return the current packet event header
a4fa4e36
MK
442 */
443 public StructDefinition getCurrentPacketEventHeader() {
6c7592e1
MK
444 if (fCurrentTracePacketHeaderDef instanceof StructDefinition) {
445 return (StructDefinition) fCurrentTracePacketHeaderDef;
446 }
447 return null;
a4fa4e36 448 }
866e5b51 449}
This page took 0.131069 seconds and 5 git commands to generate.