TMF: Do not keep event matches by default when no processing unit is set
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / CTFStreamInputPacketReader.java
CommitLineData
866e5b51 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2011, 2014 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 *
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;
526c823c 15import java.nio.ByteBuffer;
866e5b51 16
a4fa4e36 17import org.eclipse.jdt.annotation.NonNull;
733c614c 18import org.eclipse.jdt.annotation.Nullable;
c26d0fe0 19import org.eclipse.linuxtools.ctf.core.CTFStrings;
866e5b51 20import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
a4fa4e36 21import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
486efb2e 22import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
a4fa4e36
MK
23import org.eclipse.linuxtools.ctf.core.event.scope.IDefinitionScope;
24import org.eclipse.linuxtools.ctf.core.event.scope.LexicalScope;
866e5b51 25import org.eclipse.linuxtools.ctf.core.event.types.Definition;
cc98c947 26import org.eclipse.linuxtools.ctf.core.event.types.IDefinition;
a4fa4e36 27import org.eclipse.linuxtools.ctf.core.event.types.IntegerDeclaration;
866e5b51 28import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
21fb02fa 29import org.eclipse.linuxtools.ctf.core.event.types.SimpleDatatypeDefinition;
866e5b51
FC
30import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
31import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
32import org.eclipse.linuxtools.ctf.core.event.types.VariantDefinition;
8e964be1 33import org.eclipse.linuxtools.internal.ctf.core.event.EventDeclaration;
ce2388e0 34import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
866e5b51 35
a4fa4e36
MK
36import com.google.common.collect.ImmutableList;
37
866e5b51 38/**
d37aaa7f 39 * CTF trace packet reader. Reads the events of a packet of a trace file.
5c7202b5 40 *
d37aaa7f
FC
41 * @author Matthew Khouzam
42 * @author Simon Marchi
d84419e1 43 * @since 3.0
866e5b51 44 */
d84419e1 45public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseable {
866e5b51
FC
46
47 // ------------------------------------------------------------------------
6bdc9fac 48 // Attributes
866e5b51
FC
49 // ------------------------------------------------------------------------
50
6bdc9fac 51 /** BitBuffer used to read the trace file. */
733c614c
MK
52 @Nullable
53 private BitBuffer fBitBuffer;
866e5b51 54
6bdc9fac 55 /** StreamInputReader that uses this StreamInputPacketReader. */
d84419e1 56 private final CTFStreamInputReader fStreamInputReader;
866e5b51 57
6bdc9fac 58 /** Trace packet header. */
a4fa4e36 59 private final StructDeclaration fTracePacketHeaderDecl;
866e5b51 60
6bdc9fac 61 /** Stream packet context definition. */
a4fa4e36 62 private final StructDeclaration fStreamPacketContextDecl;
866e5b51 63
6bdc9fac 64 /** Stream event header definition. */
a4fa4e36 65 private final StructDeclaration fStreamEventHeaderDecl;
866e5b51 66
c26d0fe0 67 /** Stream event context definition. */
a4fa4e36 68 private final StructDeclaration fStreamEventContextDecl;
866e5b51 69
a4fa4e36
MK
70 private StructDefinition fCurrentTracePacketHeaderDef;
71 private StructDefinition fCurrentStreamEventHeaderDef;
72 private Definition fCurrentStreamPacketContextDef;
6bdc9fac 73 /** Reference to the index entry of the current packet. */
2882273c 74 private StreamInputPacketIndexEntry fCurrentPacket = null;
6bdc9fac 75
866e5b51 76 /**
6bdc9fac
AM
77 * Last timestamp recorded.
78 *
79 * Needed to calculate the complete timestamp values for the events with
80 * compact headers.
866e5b51 81 */
2882273c 82 private long fLastTimestamp = 0;
6bdc9fac
AM
83
84 /** CPU id of current packet. */
2882273c 85 private int fCurrentCpu = 0;
866e5b51 86
2882273c 87 private int fLostEventsInThisPacket;
5c7202b5 88
2882273c 89 private long fLostEventsDuration;
c26d0fe0 90
2882273c 91 private boolean fHasLost = false;
c26d0fe0 92
866e5b51 93 // ------------------------------------------------------------------------
6bdc9fac 94 // Constructors
866e5b51
FC
95 // ------------------------------------------------------------------------
96
97 /**
98 * Constructs a StreamInputPacketReader.
99 *
100 * @param streamInputReader
101 * The StreamInputReader to which this packet reader belongs to.
102 */
d84419e1 103 public CTFStreamInputPacketReader(CTFStreamInputReader streamInputReader) {
2882273c 104 fStreamInputReader = streamInputReader;
866e5b51 105
6bdc9fac 106 /* Set the BitBuffer's byte order. */
2882273c
MK
107 fBitBuffer = new BitBuffer();
108 fBitBuffer.setByteOrder(streamInputReader.getByteOrder());
33656d8e 109
d84419e1 110 final CTFStream currentStream = streamInputReader.getStreamInput().getStream();
a4fa4e36
MK
111 fTracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
112 fStreamPacketContextDecl = currentStream.getPacketContextDecl();
113 fStreamEventHeaderDecl = currentStream.getEventHeaderDecl();
114 fStreamEventContextDecl = currentStream.getEventContextDecl();
115 }
6bdc9fac 116
a4fa4e36
MK
117 /**
118 * Get the event context defintiion
119 *
120 * @param input
121 * the bitbuffer to read from
122 * @return an context definition, can be null
123 * @throws CTFReaderException
124 * out of bounds exception or such
a4fa4e36
MK
125 */
126 public StructDefinition getEventContextDefinition(@NonNull BitBuffer input) throws CTFReaderException {
70f60307 127 return fStreamEventContextDecl.createDefinition(fStreamInputReader.getStreamInput(), LexicalScope.STREAM_EVENT_CONTEXT, input);
a4fa4e36 128 }
6bdc9fac 129
a4fa4e36
MK
130 /**
131 * Get the stream context defintiion
132 *
133 * @param input
134 * the bitbuffer to read from
135 * @return an context definition, can be null
136 * @throws CTFReaderException
137 * out of bounds exception or such
a4fa4e36
MK
138 */
139 public StructDefinition getStreamEventHeaderDefinition(@NonNull BitBuffer input) throws CTFReaderException {
70f60307 140 return fStreamEventHeaderDecl.createDefinition(this, LexicalScope.EVENT_HEADER, input);
a4fa4e36 141 }
6bdc9fac 142
a4fa4e36
MK
143 /**
144 * Get the packet context defintiion
145 *
146 * @param input
147 * the bitbuffer to read from
148 * @return an context definition, can be null
149 * @throws CTFReaderException
150 * out of bounds exception or such
a4fa4e36
MK
151 */
152 public StructDefinition getStreamPacketContextDefinition(@NonNull BitBuffer input) throws CTFReaderException {
70f60307 153 return fStreamPacketContextDecl.createDefinition(fStreamInputReader.getStreamInput(), LexicalScope.STREAM_PACKET_CONTEXT, input);
a4fa4e36 154 }
6bdc9fac 155
a4fa4e36
MK
156 /**
157 * Get the event header defintiion
158 *
159 * @param input
160 * the bitbuffer to read from
161 * @return an header definition, can be null
162 * @throws CTFReaderException
163 * out of bounds exception or such
a4fa4e36
MK
164 */
165 public StructDefinition getTracePacketHeaderDefinition(@NonNull BitBuffer input) throws CTFReaderException {
70f60307 166 return fTracePacketHeaderDecl.createDefinition(fStreamInputReader.getStreamInput().getStream().getTrace(), LexicalScope.TRACE_PACKET_HEADER, input);
6bdc9fac 167 }
866e5b51 168
5d1c6919
PT
169 /**
170 * Dispose the StreamInputPacketReader
5d1c6919 171 */
dd9752d5
AM
172 @Override
173 public void close() {
733c614c 174 fBitBuffer = null;
5d1c6919
PT
175 }
176
866e5b51
FC
177 // ------------------------------------------------------------------------
178 // Getters/Setters/Predicates
179 // ------------------------------------------------------------------------
180
9ac2eb62
MK
181 /**
182 * Gets the current packet
183 *
184 * @return the current packet
185 */
486efb2e 186 StreamInputPacketIndexEntry getCurrentPacket() {
2882273c 187 return fCurrentPacket;
866e5b51
FC
188 }
189
9ac2eb62
MK
190 /**
191 * Gets the CPU (core) number
192 *
193 * @return the CPU (core) number
194 */
866e5b51 195 public int getCPU() {
2882273c 196 return fCurrentCpu;
866e5b51
FC
197 }
198
199 @Override
a4fa4e36
MK
200 public LexicalScope getScopePath() {
201 return LexicalScope.PACKET;
866e5b51
FC
202 }
203
204 // ------------------------------------------------------------------------
205 // Operations
206 // ------------------------------------------------------------------------
207
866e5b51
FC
208 /**
209 * Changes the current packet to the given one.
210 *
211 * @param currentPacket
212 * The index entry of the packet to switch to.
db8e8f7d
AM
213 * @throws CTFReaderException
214 * If we get an error reading the packet
866e5b51 215 */
db8e8f7d 216 void setCurrentPacket(StreamInputPacketIndexEntry currentPacket) throws CTFReaderException {
c26d0fe0 217 StreamInputPacketIndexEntry prevPacket = null;
2882273c 218 fCurrentPacket = currentPacket;
866e5b51 219
2882273c 220 if (fCurrentPacket != null) {
866e5b51
FC
221 /*
222 * Change the map of the BitBuffer.
223 */
526c823c 224 ByteBuffer bb = null;
866e5b51 225 try {
2882273c 226 bb = fStreamInputReader.getStreamInput().getByteBufferAt(
a4fa4e36
MK
227 fCurrentPacket.getOffsetBytes(),
228 (fCurrentPacket.getPacketSizeBits() + 7) / 8);
866e5b51 229 } catch (IOException e) {
cf9a28da 230 throw new CTFReaderException(e.getMessage(), e);
866e5b51
FC
231 }
232
733c614c
MK
233 BitBuffer bitBuffer = new BitBuffer(bb);
234 fBitBuffer = bitBuffer;
866e5b51
FC
235 /*
236 * Read trace packet header.
237 */
a4fa4e36 238 if (fTracePacketHeaderDecl != null) {
733c614c 239 fCurrentTracePacketHeaderDef = getTracePacketHeaderDefinition(bitBuffer);
866e5b51
FC
240 }
241
242 /*
243 * Read stream packet context.
244 */
a4fa4e36 245 if (fStreamPacketContextDecl != null) {
733c614c 246 fCurrentStreamPacketContextDef = getStreamPacketContextDefinition(bitBuffer);
33656d8e 247
132a02b0 248 /* Read CPU ID */
2882273c
MK
249 if (getCurrentPacket().getTarget() != null) {
250 fCurrentCpu = (int) getCurrentPacket().getTargetId();
866e5b51 251 }
21fb02fa 252
132a02b0 253 /* Read number of lost events */
2882273c
MK
254 fLostEventsInThisPacket = (int) getCurrentPacket().getLostEvents();
255 if (fLostEventsInThisPacket != 0) {
256 fHasLost = true;
c26d0fe0
AM
257 /*
258 * Compute the duration of the lost event time range. If the
259 * current packet is the first packet, duration will be set
260 * to 1.
261 */
262 long lostEventsStartTime;
2882273c 263 int index = fStreamInputReader.getStreamInput().getIndex().getEntries().indexOf(currentPacket);
c26d0fe0
AM
264 if (index == 0) {
265 lostEventsStartTime = currentPacket.getTimestampBegin() + 1;
266 } else {
2882273c 267 prevPacket = fStreamInputReader.getStreamInput().getIndex().getEntries().get(index - 1);
c26d0fe0
AM
268 lostEventsStartTime = prevPacket.getTimestampEnd();
269 }
2882273c 270 fLostEventsDuration = Math.abs(lostEventsStartTime - currentPacket.getTimestampBegin());
c26d0fe0 271 }
866e5b51
FC
272 }
273
274 /*
275 * Use the timestamp begin of the packet as the reference for the
276 * timestamp reconstitution.
277 */
2882273c 278 fLastTimestamp = currentPacket.getTimestampBegin();
866e5b51 279 } else {
733c614c 280 fBitBuffer = null;
2882273c 281 fLastTimestamp = 0;
866e5b51
FC
282 }
283 }
284
285 /**
286 * Returns whether it is possible to read any more events from this packet.
287 *
288 * @return True if it is possible to read any more events from this packet.
289 */
290 public boolean hasMoreEvents() {
733c614c
MK
291 BitBuffer bitBuffer = fBitBuffer;
292 StreamInputPacketIndexEntry currentPacket = fCurrentPacket;
293 if (currentPacket != null && bitBuffer != null) {
294 return fHasLost || (bitBuffer.position() < currentPacket.getContentSizeBits());
866e5b51
FC
295 }
296 return false;
297 }
298
299 /**
300 * Reads the next event of the packet into the right event definition.
301 *
302 * @return The event definition containing the event data that was just
303 * read.
304 * @throws CTFReaderException
be6df2d8 305 * If there was a problem reading the trace
866e5b51
FC
306 */
307 public EventDefinition readNextEvent() throws CTFReaderException {
1fbaecd1 308 /* Default values for those fields */
b73145e2 309 long eventID = EventDeclaration.UNSET_EVENT_ID;
866e5b51 310 long timestamp = 0;
2882273c
MK
311 if (fHasLost) {
312 fHasLost = false;
a4fa4e36
MK
313 EventDeclaration lostEventDeclaration = EventDeclaration.getLostEventDeclaration();
314 StructDeclaration lostFields = lostEventDeclaration.getFields();
315 // this is a hard coded map, we know it's not null
2db699c2 316 IntegerDeclaration lostFieldsDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_FIELD);
a4fa4e36
MK
317 if (lostFieldsDecl == null)
318 {
319 throw new IllegalStateException("Lost events count not declared!"); //$NON-NLS-1$
320 }
2db699c2 321 IntegerDeclaration lostEventsDurationDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_DURATION);
a4fa4e36
MK
322 if (lostEventsDurationDecl == null) {
323 throw new IllegalStateException("Lost events duration not declared!"); //$NON-NLS-1$
324 }
325 IntegerDefinition lostDurationDef = new IntegerDefinition(lostFieldsDecl, null, CTFStrings.LOST_EVENTS_DURATION, fLostEventsDuration);
326 IntegerDefinition lostCountDef = new IntegerDefinition(lostEventsDurationDecl, null, CTFStrings.LOST_EVENTS_FIELD, fLostEventsInThisPacket);
327 IntegerDefinition[] fields = new IntegerDefinition[] { lostCountDef, lostDurationDef };
328 /* this is weird notation, but it's the java notation */
329 final ImmutableList<String> fieldNameList = ImmutableList.<String> builder().add(CTFStrings.LOST_EVENTS_FIELD).add(CTFStrings.LOST_EVENTS_DURATION).build();
330 return new EventDefinition(
331 lostEventDeclaration,
332 fStreamInputReader,
333 fLastTimestamp,
334 null,
335 null,
336 null,
337 new StructDefinition(
338 lostFields,
339 this, "fields", //$NON-NLS-1$
340 fieldNameList,
341 fields
342 ));
343
33656d8e 344 }
132a02b0 345
2882273c 346 final BitBuffer currentBitBuffer = fBitBuffer;
733c614c
MK
347 if( currentBitBuffer == null ) {
348 return null;
349 }
cf9a28da 350 final long posStart = currentBitBuffer.position();
1fbaecd1 351 /* Read the stream event header. */
a4fa4e36
MK
352 if (fStreamEventHeaderDecl != null) {
353 fCurrentStreamEventHeaderDef = getStreamEventHeaderDefinition(currentBitBuffer);
866e5b51 354
1fbaecd1 355 /* Check for the event id. */
cc98c947 356 IDefinition idDef = fCurrentStreamEventHeaderDef.lookupDefinition("id"); //$NON-NLS-1$
1fbaecd1
AM
357 if (idDef instanceof SimpleDatatypeDefinition) {
358 eventID = ((SimpleDatatypeDefinition) idDef).getIntegerValue();
b8cb28f6 359 } else if (idDef != null) {
816fde81 360 throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
b8cb28f6 361 }
866e5b51 362
c26d0fe0
AM
363 /*
364 * Get the timestamp from the event header (may be overridden later
365 * on)
366 */
a4fa4e36 367 IntegerDefinition timestampDef = fCurrentStreamEventHeaderDef.lookupInteger("timestamp"); //$NON-NLS-1$
0594c61c
AM
368 if (timestampDef != null) {
369 timestamp = calculateTimestamp(timestampDef);
6bdc9fac 370 } // else timestamp remains 0
1fbaecd1
AM
371
372 /* Check for the variant v. */
cc98c947 373 IDefinition variantDef = fCurrentStreamEventHeaderDef.lookupDefinition("v"); //$NON-NLS-1$
6bdc9fac 374 if (variantDef instanceof VariantDefinition) {
866e5b51 375
1fbaecd1 376 /* Get the variant current field */
6bdc9fac 377 StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
866e5b51 378
21fb02fa
MK
379 /*
380 * Try to get the id field in the current field of the variant.
381 * If it is present, it overrides the previously read event id.
382 */
cc98c947 383 IDefinition idIntegerDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
6bdc9fac
AM
384 if (idIntegerDef instanceof IntegerDefinition) {
385 eventID = ((IntegerDefinition) idIntegerDef).getValue();
21fb02fa 386 }
866e5b51 387
c26d0fe0
AM
388 /*
389 * Get the timestamp. This would overwrite any previous
390 * timestamp definition
391 */
cc98c947 392 IDefinition def = variantCurrentField.lookupDefinition("timestamp"); //$NON-NLS-1$
0594c61c
AM
393 if (def instanceof IntegerDefinition) {
394 timestamp = calculateTimestamp((IntegerDefinition) def);
6bdc9fac 395 }
21fb02fa 396 }
866e5b51
FC
397 }
398
1fbaecd1 399 /* Get the right event definition using the event id. */
a4fa4e36
MK
400 IEventDeclaration eventDeclaration = fStreamInputReader.getStreamInput().getStream().getEvents().get(eventID);
401 if (eventDeclaration == null) {
866e5b51
FC
402 throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
403 }
733c614c 404 EventDefinition eventDef = eventDeclaration.createDefinition(fStreamInputReader, currentBitBuffer, timestamp);
866e5b51
FC
405
406 /*
407 * Set the event timestamp using the timestamp calculated by
408 * updateTimestamp.
409 */
866e5b51 410
cf9a28da
MK
411 if (posStart == currentBitBuffer.position()) {
412 throw new CTFReaderException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$
413 }
414
866e5b51
FC
415 return eventDef;
416 }
417
418 /**
419 * Calculates the timestamp value of the event, possibly using the timestamp
420 * from the last event.
421 *
422 * @param timestampDef
423 * Integer definition of the timestamp.
424 * @return The calculated timestamp value.
425 */
426 private long calculateTimestamp(IntegerDefinition timestampDef) {
427 long newval;
428 long majorasbitmask;
429 int len = timestampDef.getDeclaration().getLength();
430
431 /*
432 * If the timestamp length is 64 bits, it is a full timestamp.
433 */
434 if (timestampDef.getDeclaration().getLength() == 64) {
2882273c
MK
435 fLastTimestamp = timestampDef.getValue();
436 return fLastTimestamp;
866e5b51
FC
437 }
438
439 /*
440 * Bit mask to keep / remove all old / new bits.
441 */
442 majorasbitmask = (1L << len) - 1;
443
444 /*
445 * If the new value is smaller than the corresponding bits of the last
446 * timestamp, we assume an overflow of the compact representation.
447 */
448 newval = timestampDef.getValue();
2882273c 449 if (newval < (fLastTimestamp & majorasbitmask)) {
866e5b51
FC
450 newval = newval + (1L << len);
451 }
452
453 /* Keep only the high bits of the old value */
2882273c 454 fLastTimestamp = fLastTimestamp & ~majorasbitmask;
866e5b51
FC
455
456 /* Then add the low bits of the new value */
2882273c 457 fLastTimestamp = fLastTimestamp + newval;
866e5b51 458
2882273c 459 return fLastTimestamp;
866e5b51
FC
460 }
461
462 @Override
463 public Definition lookupDefinition(String lookupPath) {
f159df11 464 if (lookupPath.equals(LexicalScope.STREAM_PACKET_CONTEXT.toString())) {
a4fa4e36
MK
465 return fCurrentStreamPacketContextDef;
466 }
f159df11 467 if (lookupPath.equals(LexicalScope.TRACE_PACKET_HEADER.toString())) {
a4fa4e36
MK
468 return fCurrentTracePacketHeaderDef;
469 }
866e5b51
FC
470 return null;
471 }
a4fa4e36
MK
472
473 /**
474 * Get stream event header
475 *
476 * @return the stream event header
a4fa4e36
MK
477 */
478 public StructDefinition getCurrentStreamEventHeader() {
479 return fCurrentStreamEventHeaderDef;
480 }
481
482 /**
483 * Get the current packet event header
484 *
485 * @return the current packet event header
a4fa4e36
MK
486 */
487 public StructDefinition getCurrentPacketEventHeader() {
488 return fCurrentTracePacketHeaderDef;
489 }
866e5b51 490}
This page took 0.070964 seconds and 5 git commands to generate.