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