Change some @since to 1.1 for things that were really added in 1.1
[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,
408f954e 345 fStreamInputReader.getCPU(),
74d58b9b 346 lostEventsTimestamp,
a4fa4e36
MK
347 null,
348 null,
349 null,
408f954e 350 null,
a4fa4e36
MK
351 new StructDefinition(
352 lostFields,
353 this, "fields", //$NON-NLS-1$
a4fa4e36
MK
354 fields
355 ));
356
33656d8e 357 }
132a02b0 358
1fbaecd1 359 /* Read the stream event header. */
a4fa4e36 360 if (fStreamEventHeaderDecl != null) {
6c7592e1 361 if (fStreamEventHeaderDecl instanceof IEventHeaderDeclaration) {
94c255ef 362 fCurrentStreamEventHeaderDef = (ICompositeDefinition) fStreamEventHeaderDecl.createDefinition(EVENT_HEADER_SCOPE, "", currentBitBuffer); //$NON-NLS-1$
6c7592e1
MK
363 EventHeaderDefinition ehd = (EventHeaderDefinition) fCurrentStreamEventHeaderDef;
364 eventID = ehd.getId();
6c7592e1 365 } else {
94c255ef 366 fCurrentStreamEventHeaderDef = ((StructDeclaration) fStreamEventHeaderDecl).createDefinition(EVENT_HEADER_SCOPE, ILexicalScope.EVENT_HEADER, currentBitBuffer);
6c7592e1
MK
367 StructDefinition StructEventHeaderDef = (StructDefinition) fCurrentStreamEventHeaderDef;
368 /* Check for the event id. */
369 IDefinition idDef = StructEventHeaderDef.lookupDefinition("id"); //$NON-NLS-1$
370 SimpleDatatypeDefinition simpleIdDef = null;
371 if (idDef instanceof SimpleDatatypeDefinition) {
372 simpleIdDef = ((SimpleDatatypeDefinition) idDef);
373 } else if (idDef != null) {
680f9173 374 throw new CTFIOException("Id defintion not an integer, enum or float definiton in event header."); //$NON-NLS-1$
6c7592e1 375 }
6c7592e1
MK
376 /* Check for the variant v. */
377 IDefinition variantDef = StructEventHeaderDef.lookupDefinition("v"); //$NON-NLS-1$
378 if (variantDef instanceof VariantDefinition) {
866e5b51 379
6c7592e1
MK
380 /* Get the variant current field */
381 StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
866e5b51 382
6c7592e1
MK
383 /*
384 * Try to get the id field in the current field of the
385 * variant. If it is present, it overrides the previously
386 * read event id.
387 */
388 IDefinition vIdDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
389 if (vIdDef instanceof IntegerDefinition) {
390 simpleIdDef = (SimpleDatatypeDefinition) vIdDef;
391 }
866e5b51 392
6bdc9fac 393 }
6c7592e1 394 if (simpleIdDef != null) {
5f715709 395 eventID = simpleIdDef.getIntegerValue().intValue();
6c7592e1 396 }
21fb02fa 397 }
866e5b51 398 }
1fbaecd1 399 /* Get the right event definition using the event id. */
94c255ef 400 EventDeclaration eventDeclaration = (EventDeclaration) fStreamInputReader.getStreamInput().getStream().getEventDeclaration(eventID);
a4fa4e36 401 if (eventDeclaration == null) {
680f9173 402 throw new CTFIOException("Incorrect event id : " + eventID); //$NON-NLS-1$
866e5b51 403 }
5b341dc8
MK
404 EventDefinition eventDef = eventDeclaration.createDefinition(fStreamInputReader, fCurrentStreamEventHeaderDef, currentBitBuffer, fLastTimestamp);
405 fLastTimestamp = eventDef.getTimestamp();
866e5b51
FC
406 /*
407 * Set the event timestamp using the timestamp calculated by
408 * updateTimestamp.
409 */
866e5b51 410
cf9a28da 411 if (posStart == currentBitBuffer.position()) {
680f9173 412 throw new CTFIOException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$
cf9a28da
MK
413 }
414
866e5b51
FC
415 return eventDef;
416 }
417
866e5b51
FC
418 @Override
419 public Definition lookupDefinition(String lookupPath) {
fbe6fa6f 420 if (lookupPath.equals(ILexicalScope.STREAM_PACKET_CONTEXT.getPath())) {
6c7592e1 421 return (Definition) fCurrentStreamPacketContextDef;
a4fa4e36 422 }
fbe6fa6f 423 if (lookupPath.equals(ILexicalScope.TRACE_PACKET_HEADER.getPath())) {
6c7592e1 424 return (Definition) fCurrentTracePacketHeaderDef;
a4fa4e36 425 }
866e5b51
FC
426 return null;
427 }
a4fa4e36 428
6c7592e1
MK
429
430 /**
431 * Get stream event header
432 *
433 * @return the stream event header
6c7592e1
MK
434 */
435 public ICompositeDefinition getStreamEventHeaderDefinition() {
a4fa4e36
MK
436 return fCurrentStreamEventHeaderDef;
437 }
438
439 /**
440 * Get the current packet event header
441 *
442 * @return the current packet event header
a4fa4e36
MK
443 */
444 public StructDefinition getCurrentPacketEventHeader() {
6c7592e1
MK
445 if (fCurrentTracePacketHeaderDef instanceof StructDefinition) {
446 return (StructDefinition) fCurrentTracePacketHeaderDef;
447 }
448 return null;
a4fa4e36 449 }
866e5b51 450}
This page took 0.092658 seconds and 5 git commands to generate.