[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
1 /*******************************************************************************
2 * Copyright (c) 2011, 2015 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:
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
13 *******************************************************************************/
14 package org.eclipse.tracecompass.ctf.core.trace;
15
16 import java.io.IOException;
17 import java.nio.ByteBuffer;
18 import java.nio.channels.FileChannel.MapMode;
19
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.eclipse.tracecompass.ctf.core.CTFException;
23 import org.eclipse.tracecompass.ctf.core.CTFStrings;
24 import org.eclipse.tracecompass.ctf.core.event.EventDefinition;
25 import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
26 import org.eclipse.tracecompass.ctf.core.event.LostEventDeclaration;
27 import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
28 import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope;
29 import org.eclipse.tracecompass.ctf.core.event.scope.ILexicalScope;
30 import org.eclipse.tracecompass.ctf.core.event.scope.LexicalScope;
31 import org.eclipse.tracecompass.ctf.core.event.types.Definition;
32 import org.eclipse.tracecompass.ctf.core.event.types.ICompositeDefinition;
33 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
34 import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
35 import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
36 import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
37 import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
38 import org.eclipse.tracecompass.ctf.core.event.types.SimpleDatatypeDefinition;
39 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
40 import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
41 import org.eclipse.tracecompass.ctf.core.event.types.VariantDefinition;
42 import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer;
43 import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
44 import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition;
45
46 /**
47 * CTF trace packet reader. Reads the events of a packet of a trace file.
48 *
49 * @author Matthew Khouzam
50 * @author Simon Marchi
51 */
52 public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseable {
53
54 // ------------------------------------------------------------------------
55 // Attributes
56 // ------------------------------------------------------------------------
57
58 private static final int BITS_PER_BYTE = Byte.SIZE;
59
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
73 /** BitBuffer used to read the trace file. */
74 @Nullable
75 private BitBuffer fBitBuffer;
76
77 /** StreamInputReader that uses this StreamInputPacketReader. */
78 private final CTFStreamInputReader fStreamInputReader;
79
80 /** Trace packet header. */
81 private final StructDeclaration fTracePacketHeaderDecl;
82
83 /** Stream packet context definition. */
84 private final StructDeclaration fStreamPacketContextDecl;
85
86 /** Stream event header definition. */
87 private final IDeclaration fStreamEventHeaderDecl;
88
89 /** Stream event context definition. */
90 private final StructDeclaration fStreamEventContextDecl;
91
92 private ICompositeDefinition fCurrentTracePacketHeaderDef;
93 private ICompositeDefinition fCurrentStreamEventHeaderDef;
94 private ICompositeDefinition fCurrentStreamPacketContextDef;
95 /** Reference to the index entry of the current packet. */
96 private ICTFPacketDescriptor fCurrentPacket = null;
97
98 /**
99 * Last timestamp recorded.
100 *
101 * Needed to calculate the complete timestamp values for the events with
102 * compact headers.
103 */
104 private long fLastTimestamp = 0;
105
106 /** CPU id of current packet. */
107 private int fCurrentCpu = 0;
108
109 private int fLostEventsInThisPacket;
110
111 private boolean fHasLost = false;
112
113 // ------------------------------------------------------------------------
114 // Constructors
115 // ------------------------------------------------------------------------
116
117 /**
118 * Constructs a StreamInputPacketReader.
119 *
120 * @param streamInputReader
121 * The StreamInputReader to which this packet reader belongs to.
122 */
123 public CTFStreamInputPacketReader(CTFStreamInputReader streamInputReader) {
124 fStreamInputReader = streamInputReader;
125
126 /* Set the BitBuffer's byte order. */
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);
132
133 final CTFStream currentStream = streamInputReader.getStreamInput().getStream();
134 fTracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
135 fStreamPacketContextDecl = currentStream.getPacketContextDecl();
136 fStreamEventHeaderDecl = currentStream.getEventHeaderDeclaration();
137 fStreamEventContextDecl = currentStream.getEventContextDecl();
138 }
139
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
146 * @throws CTFException
147 * out of bounds exception or such
148 */
149 public StructDefinition getEventContextDefinition(@NonNull BitBuffer input) throws CTFException {
150 return fStreamEventContextDecl.createDefinition(fStreamInputReader.getStreamInput(), ILexicalScope.STREAM_EVENT_CONTEXT, input);
151 }
152
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
159 * @throws CTFException
160 * out of bounds exception or such
161 */
162 public StructDefinition getStreamPacketContextDefinition(@NonNull BitBuffer input) throws CTFException {
163 return fStreamPacketContextDecl.createDefinition(fStreamInputReader.getStreamInput(), ILexicalScope.STREAM_PACKET_CONTEXT, input);
164 }
165
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
172 * @throws CTFException
173 * out of bounds exception or such
174 */
175 public StructDefinition getTracePacketHeaderDefinition(@NonNull BitBuffer input) throws CTFException {
176 return fTracePacketHeaderDecl.createDefinition(fStreamInputReader.getStreamInput().getStream().getTrace(), ILexicalScope.TRACE_PACKET_HEADER, input);
177 }
178
179 /**
180 * Dispose the StreamInputPacketReader
181 */
182 @Override
183 public void close() {
184 fBitBuffer = null;
185 }
186
187 // ------------------------------------------------------------------------
188 // Getters/Setters/Predicates
189 // ------------------------------------------------------------------------
190
191 /**
192 * Gets the current packet
193 *
194 * @return the current packet
195 */
196 ICTFPacketDescriptor getCurrentPacket() {
197 return fCurrentPacket;
198 }
199
200 /**
201 * Gets the CPU (core) number
202 *
203 * @return the CPU (core) number
204 */
205 public int getCPU() {
206 return fCurrentCpu;
207 }
208
209 @Override
210 public LexicalScope getScopePath() {
211 return ILexicalScope.PACKET;
212 }
213
214 // ------------------------------------------------------------------------
215 // Operations
216 // ------------------------------------------------------------------------
217
218 @NonNull
219 private ByteBuffer getByteBufferAt(long position, long size) throws CTFException, IOException {
220 ByteBuffer map = SafeMappedByteBuffer.map(fStreamInputReader.getFc(), MapMode.READ_ONLY, position, size);
221 if (map == null) {
222 throw new CTFIOException("Failed to allocate mapped byte buffer"); //$NON-NLS-1$
223 }
224 return map;
225 }
226
227 /**
228 * Changes the current packet to the given one.
229 *
230 * @param currentPacket
231 * The index entry of the packet to switch to.
232 * @throws CTFException
233 * If we get an error reading the packet
234 * @since 1.0
235 */
236 public void setCurrentPacket(ICTFPacketDescriptor currentPacket) throws CTFException {
237 fCurrentPacket = currentPacket;
238 fHasLost = false;
239
240 if (fCurrentPacket != null) {
241 /*
242 * Change the map of the BitBuffer.
243 */
244 ByteBuffer bb = null;
245 try {
246 bb = getByteBufferAt(fCurrentPacket.getOffsetBytes(), (fCurrentPacket.getPacketSizeBits() + BITS_PER_BYTE - 1) / BITS_PER_BYTE);
247 } catch (IOException e) {
248 throw new CTFIOException(e.getMessage(), e);
249 }
250
251 BitBuffer bitBuffer = new BitBuffer(bb);
252 fBitBuffer = bitBuffer;
253 /*
254 * Read trace packet header.
255 */
256 if (fTracePacketHeaderDecl != null) {
257 fCurrentTracePacketHeaderDef = getTracePacketHeaderDefinition(bitBuffer);
258 }
259
260 /*
261 * Read stream packet context.
262 */
263 if (fStreamPacketContextDecl != null) {
264 fCurrentStreamPacketContextDef = getStreamPacketContextDefinition(bitBuffer);
265
266 /* Read CPU ID */
267 if (getCurrentPacket().getTarget() != null) {
268 fCurrentCpu = (int) getCurrentPacket().getTargetId();
269 }
270
271 /* Read number of lost events */
272 fLostEventsInThisPacket = (int) getCurrentPacket().getLostEvents();
273 if (fLostEventsInThisPacket != 0) {
274 fHasLost = true;
275 }
276 }
277
278 /*
279 * Use the timestamp begin of the packet as the reference for the
280 * timestamp reconstitution.
281 */
282 fLastTimestamp = Math.max(currentPacket.getTimestampBegin(), 0);
283 } else {
284 fBitBuffer = null;
285 fLastTimestamp = 0;
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() {
295 BitBuffer bitBuffer = fBitBuffer;
296 ICTFPacketDescriptor currentPacket = fCurrentPacket;
297 if (currentPacket != null && bitBuffer != null) {
298 return fHasLost || (bitBuffer.position() < currentPacket.getContentSizeBits());
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.
308 * @throws CTFException
309 * If there was a problem reading the trace
310 */
311 public EventDefinition readNextEvent() throws CTFException {
312 /* Default values for those fields */
313 // compromise since we cannot have 64 bit addressing of arrays yet.
314 int eventID = (int) IEventDeclaration.UNSET_EVENT_ID;
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()) {
325 fHasLost = false;
326 IEventDeclaration lostEventDeclaration = LostEventDeclaration.INSTANCE;
327 StructDeclaration lostFields = lostEventDeclaration.getFields();
328 // this is a hard coded map, we know it's not null
329 IntegerDeclaration lostFieldsDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_FIELD);
330 if (lostFieldsDecl == null)
331 {
332 throw new IllegalStateException("Lost events count not declared!"); //$NON-NLS-1$
333 }
334 IntegerDeclaration lostEventsDurationDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_DURATION);
335 if (lostEventsDurationDecl == null) {
336 throw new IllegalStateException("Lost events duration not declared!"); //$NON-NLS-1$
337 }
338 long lostEventsTimestamp = fLastTimestamp;
339 long lostEventsDuration = currentPacket.getTimestampEnd() - lostEventsTimestamp;
340 IntegerDefinition lostDurationDef = new IntegerDefinition(lostFieldsDecl, null, CTFStrings.LOST_EVENTS_DURATION, lostEventsDuration);
341 IntegerDefinition lostCountDef = new IntegerDefinition(lostEventsDurationDecl, null, CTFStrings.LOST_EVENTS_FIELD, fLostEventsInThisPacket);
342 IntegerDefinition[] fields = new IntegerDefinition[] { lostCountDef, lostDurationDef };
343 return new EventDefinition(
344 lostEventDeclaration,
345 fStreamInputReader,
346 lostEventsTimestamp,
347 null,
348 null,
349 null,
350 new StructDefinition(
351 lostFields,
352 this, "fields", //$NON-NLS-1$
353 fields
354 ));
355
356 }
357
358 /* Read the stream event header. */
359 if (fStreamEventHeaderDecl != null) {
360 if (fStreamEventHeaderDecl instanceof IEventHeaderDeclaration) {
361 fCurrentStreamEventHeaderDef = (ICompositeDefinition) fStreamEventHeaderDecl.createDefinition(EVENT_HEADER_SCOPE, "", currentBitBuffer); //$NON-NLS-1$
362 EventHeaderDefinition ehd = (EventHeaderDefinition) fCurrentStreamEventHeaderDef;
363 eventID = ehd.getId();
364 } else {
365 fCurrentStreamEventHeaderDef = ((StructDeclaration) fStreamEventHeaderDecl).createDefinition(EVENT_HEADER_SCOPE, ILexicalScope.EVENT_HEADER, currentBitBuffer);
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) {
373 throw new CTFIOException("Id defintion not an integer, enum or float definiton in event header."); //$NON-NLS-1$
374 }
375 /* Check for the variant v. */
376 IDefinition variantDef = StructEventHeaderDef.lookupDefinition("v"); //$NON-NLS-1$
377 if (variantDef instanceof VariantDefinition) {
378
379 /* Get the variant current field */
380 StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
381
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 }
391
392 }
393 if (simpleIdDef != null) {
394 eventID = simpleIdDef.getIntegerValue().intValue();
395 }
396 }
397 }
398 /* Get the right event definition using the event id. */
399 EventDeclaration eventDeclaration = (EventDeclaration) fStreamInputReader.getStreamInput().getStream().getEventDeclaration(eventID);
400 if (eventDeclaration == null) {
401 throw new CTFIOException("Incorrect event id : " + eventID); //$NON-NLS-1$
402 }
403 EventDefinition eventDef = eventDeclaration.createDefinition(fStreamInputReader, fCurrentStreamEventHeaderDef, currentBitBuffer, fLastTimestamp);
404 fLastTimestamp = eventDef.getTimestamp();
405 /*
406 * Set the event timestamp using the timestamp calculated by
407 * updateTimestamp.
408 */
409
410 if (posStart == currentBitBuffer.position()) {
411 throw new CTFIOException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$
412 }
413
414 return eventDef;
415 }
416
417 @Override
418 public Definition lookupDefinition(String lookupPath) {
419 if (lookupPath.equals(ILexicalScope.STREAM_PACKET_CONTEXT.getPath())) {
420 return (Definition) fCurrentStreamPacketContextDef;
421 }
422 if (lookupPath.equals(ILexicalScope.TRACE_PACKET_HEADER.getPath())) {
423 return (Definition) fCurrentTracePacketHeaderDef;
424 }
425 return null;
426 }
427
428
429 /**
430 * Get stream event header
431 *
432 * @return the stream event header
433 */
434 public ICompositeDefinition getStreamEventHeaderDefinition() {
435 return fCurrentStreamEventHeaderDef;
436 }
437
438 /**
439 * Get the current packet event header
440 *
441 * @return the current packet event header
442 */
443 public StructDefinition getCurrentPacketEventHeader() {
444 if (fCurrentTracePacketHeaderDef instanceof StructDefinition) {
445 return (StructDefinition) fCurrentTracePacketHeaderDef;
446 }
447 return null;
448 }
449 }
This page took 0.052263 seconds and 5 git commands to generate.