ctf: avoid array creation to iterate through scope types.
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / StreamInputPacketReader.java
CommitLineData
866e5b51 1/*******************************************************************************
8e964be1 2 * Copyright (c) 2011-2013 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;
15import java.nio.MappedByteBuffer;
16import java.nio.channels.FileChannel.MapMode;
17import java.util.Collection;
866e5b51 18
c26d0fe0 19import org.eclipse.linuxtools.ctf.core.CTFStrings;
866e5b51 20import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
8e964be1 21import org.eclipse.linuxtools.ctf.core.event.IEventDeclaration;
486efb2e 22import org.eclipse.linuxtools.ctf.core.event.io.BitBuffer;
866e5b51 23import org.eclipse.linuxtools.ctf.core.event.types.Definition;
866e5b51
FC
24import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
25import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
21fb02fa 26import org.eclipse.linuxtools.ctf.core.event.types.SimpleDatatypeDefinition;
866e5b51
FC
27import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
28import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
29import org.eclipse.linuxtools.ctf.core.event.types.VariantDefinition;
8e964be1 30import org.eclipse.linuxtools.internal.ctf.core.event.EventDeclaration;
ce2388e0 31import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
866e5b51
FC
32
33/**
d37aaa7f 34 * CTF trace packet reader. Reads the events of a packet of a trace file.
5c7202b5 35 *
d37aaa7f
FC
36 * @version 1.0
37 * @author Matthew Khouzam
38 * @author Simon Marchi
866e5b51 39 */
bfe038ff 40public class StreamInputPacketReader implements IDefinitionScope {
866e5b51
FC
41
42 // ------------------------------------------------------------------------
6bdc9fac 43 // Attributes
866e5b51
FC
44 // ------------------------------------------------------------------------
45
6bdc9fac
AM
46 /** BitBuffer used to read the trace file. */
47 private final BitBuffer bitBuffer;
866e5b51 48
6bdc9fac 49 /** StreamInputReader that uses this StreamInputPacketReader. */
866e5b51
FC
50 private final StreamInputReader streamInputReader;
51
6bdc9fac
AM
52 /** Trace packet header. */
53 private final StructDefinition tracePacketHeaderDef;
866e5b51 54
6bdc9fac
AM
55 /** Stream packet context definition. */
56 private final StructDefinition streamPacketContextDef;
866e5b51 57
6bdc9fac
AM
58 /** Stream event header definition. */
59 private final StructDefinition streamEventHeaderDef;
866e5b51 60
c26d0fe0 61 /** Stream event context definition. */
6bdc9fac 62 private final StructDefinition streamEventContextDef;
866e5b51 63
6bdc9fac
AM
64 /** Reference to the index entry of the current packet. */
65 private StreamInputPacketIndexEntry currentPacket = null;
66
866e5b51 67 /**
6bdc9fac
AM
68 * Last timestamp recorded.
69 *
70 * Needed to calculate the complete timestamp values for the events with
71 * compact headers.
866e5b51 72 */
6bdc9fac
AM
73 private long lastTimestamp = 0;
74
75 /** CPU id of current packet. */
866e5b51
FC
76 private int currentCpu = 0;
77
5c7202b5
MK
78 private int lostEventsInThisPacket;
79
c26d0fe0
AM
80 private long lostEventsDuration;
81
82 private boolean hasLost = false;
83
866e5b51 84 // ------------------------------------------------------------------------
6bdc9fac 85 // Constructors
866e5b51
FC
86 // ------------------------------------------------------------------------
87
88 /**
89 * Constructs a StreamInputPacketReader.
90 *
91 * @param streamInputReader
92 * The StreamInputReader to which this packet reader belongs to.
93 */
94 public StreamInputPacketReader(StreamInputReader streamInputReader) {
95 this.streamInputReader = streamInputReader;
96
6bdc9fac
AM
97 /* Set the BitBuffer's byte order. */
98 bitBuffer = new BitBuffer();
99 bitBuffer.setByteOrder(streamInputReader.getByteOrder());
33656d8e 100
6bdc9fac
AM
101 /* Create trace packet header definition. */
102 final Stream currentStream = streamInputReader.getStreamInput().getStream();
103 StructDeclaration tracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
104 if (tracePacketHeaderDecl != null) {
105 tracePacketHeaderDef = tracePacketHeaderDecl.createDefinition(this, "trace.packet.header"); //$NON-NLS-1$
106 } else {
107 tracePacketHeaderDef = null;
108 }
109
110 /* Create stream packet context definition. */
111 StructDeclaration streamPacketContextDecl = currentStream.getPacketContextDecl();
112 if (streamPacketContextDecl != null) {
113 streamPacketContextDef = streamPacketContextDecl.createDefinition(this, "stream.packet.context"); //$NON-NLS-1$
114 } else {
115 streamPacketContextDef = null;
116 }
117
118 /* Create stream event header definition. */
119 StructDeclaration streamEventHeaderDecl = currentStream.getEventHeaderDecl();
120 if (streamEventHeaderDecl != null) {
121 streamEventHeaderDef = streamEventHeaderDecl.createDefinition(this, "stream.event.header"); //$NON-NLS-1$
122 } else {
123 streamEventHeaderDef = null;
124 }
125
126 /* Create stream event context definition. */
127 StructDeclaration streamEventContextDecl = currentStream.getEventContextDecl();
128 if (streamEventContextDecl != null) {
129 streamEventContextDef = streamEventContextDecl.createDefinition(this, "stream.event.context"); //$NON-NLS-1$
130 } else {
131 streamEventContextDef = null;
132 }
133
134 /* Create event definitions */
8e964be1 135 Collection<IEventDeclaration> eventDecls = streamInputReader.getStreamInput().getStream().getEvents().values();
6bdc9fac 136
8e964be1 137 for (IEventDeclaration event : eventDecls) {
7ff6d3cf 138 if (!streamInputReader.getEventDefinitions().containsKey(event.getId())) {
6bdc9fac 139 EventDefinition eventDef = event.createDefinition(streamInputReader);
7ff6d3cf 140 streamInputReader.addEventDefinition(event.getId(), eventDef);
6bdc9fac
AM
141 }
142 }
143 }
866e5b51 144
5d1c6919
PT
145 /**
146 * Dispose the StreamInputPacketReader
c26d0fe0 147 *
5d1c6919
PT
148 * @since 2.0
149 */
150 public void dispose() {
151 bitBuffer.setByteBuffer(null);
152 }
153
866e5b51
FC
154 // ------------------------------------------------------------------------
155 // Getters/Setters/Predicates
156 // ------------------------------------------------------------------------
157
9ac2eb62
MK
158 /**
159 * Gets the current packet
160 *
161 * @return the current packet
162 */
486efb2e 163 StreamInputPacketIndexEntry getCurrentPacket() {
866e5b51
FC
164 return this.currentPacket;
165 }
166
9ac2eb62
MK
167 /**
168 * Gets the steamPacketContext Definition
169 *
170 * @return steamPacketContext Definition
171 */
866e5b51
FC
172 public StructDefinition getStreamPacketContextDef() {
173 return this.streamPacketContextDef;
174 }
175
45cbd8dc
AM
176 /**
177 * Gets the stream's event context definition.
178 *
179 * @return The streamEventContext definition
180 */
181 public StructDefinition getStreamEventContextDef() {
182 return streamEventContextDef;
183 }
184
9ac2eb62
MK
185 /**
186 * Gets the CPU (core) number
187 *
188 * @return the CPU (core) number
189 */
866e5b51
FC
190 public int getCPU() {
191 return this.currentCpu;
192 }
193
194 @Override
195 public String getPath() {
196 return ""; //$NON-NLS-1$
197 }
198
199 // ------------------------------------------------------------------------
200 // Operations
201 // ------------------------------------------------------------------------
202
866e5b51
FC
203 /**
204 * Changes the current packet to the given one.
205 *
206 * @param currentPacket
207 * The index entry of the packet to switch to.
db8e8f7d
AM
208 * @throws CTFReaderException
209 * If we get an error reading the packet
866e5b51 210 */
db8e8f7d 211 void setCurrentPacket(StreamInputPacketIndexEntry currentPacket) throws CTFReaderException {
c26d0fe0 212 StreamInputPacketIndexEntry prevPacket = null;
866e5b51
FC
213 this.currentPacket = currentPacket;
214
215 if (this.currentPacket != null) {
216 /*
217 * Change the map of the BitBuffer.
218 */
219 MappedByteBuffer bb = null;
220 try {
6bdc9fac 221 bb = streamInputReader.getStreamInput().getFileChannel()
788ddcbc
MK
222 .map(MapMode.READ_ONLY,
223 this.currentPacket.getOffsetBytes(),
224 (this.currentPacket.getPacketSizeBits() + 7) / 8);
866e5b51 225 } catch (IOException e) {
cf9a28da 226 throw new CTFReaderException(e.getMessage(), e);
866e5b51
FC
227 }
228
6bdc9fac 229 bitBuffer.setByteBuffer(bb);
866e5b51
FC
230
231 /*
232 * Read trace packet header.
233 */
6bdc9fac
AM
234 if (tracePacketHeaderDef != null) {
235 tracePacketHeaderDef.read(bitBuffer);
866e5b51
FC
236 }
237
238 /*
239 * Read stream packet context.
240 */
241 if (getStreamPacketContextDef() != null) {
6bdc9fac 242 getStreamPacketContextDef().read(bitBuffer);
33656d8e 243
132a02b0 244 /* Read CPU ID */
21fb02fa 245 if (this.getCurrentPacket().getTarget() != null) {
132a02b0 246 this.currentCpu = (int) this.getCurrentPacket().getTargetId();
866e5b51 247 }
21fb02fa 248
132a02b0
MK
249 /* Read number of lost events */
250 lostEventsInThisPacket = (int) this.getCurrentPacket().getLostEvents();
c26d0fe0
AM
251 if (lostEventsInThisPacket != 0) {
252 hasLost = true;
253 /*
254 * Compute the duration of the lost event time range. If the
255 * current packet is the first packet, duration will be set
256 * to 1.
257 */
258 long lostEventsStartTime;
259 int index = this.streamInputReader.getStreamInput().getIndex().getEntries().indexOf(currentPacket);
260 if (index == 0) {
261 lostEventsStartTime = currentPacket.getTimestampBegin() + 1;
262 } else {
263 prevPacket = this.streamInputReader.getStreamInput().getIndex().getEntries().get(index - 1);
264 lostEventsStartTime = prevPacket.getTimestampEnd();
265 }
266 lostEventsDuration = Math.abs(lostEventsStartTime - currentPacket.getTimestampBegin());
267 }
866e5b51
FC
268 }
269
270 /*
271 * Use the timestamp begin of the packet as the reference for the
272 * timestamp reconstitution.
273 */
ce2388e0 274 lastTimestamp = currentPacket.getTimestampBegin();
866e5b51 275 } else {
6bdc9fac 276 bitBuffer.setByteBuffer(null);
866e5b51
FC
277
278 lastTimestamp = 0;
279 }
280 }
281
282 /**
283 * Returns whether it is possible to read any more events from this packet.
284 *
285 * @return True if it is possible to read any more events from this packet.
286 */
287 public boolean hasMoreEvents() {
288 if (currentPacket != null) {
c26d0fe0 289 return hasLost || (bitBuffer.position() < currentPacket.getContentSizeBits());
866e5b51
FC
290 }
291 return false;
292 }
293
294 /**
295 * Reads the next event of the packet into the right event definition.
296 *
297 * @return The event definition containing the event data that was just
298 * read.
299 * @throws CTFReaderException
be6df2d8 300 * If there was a problem reading the trace
866e5b51
FC
301 */
302 public EventDefinition readNextEvent() throws CTFReaderException {
1fbaecd1 303 /* Default values for those fields */
b73145e2 304 long eventID = EventDeclaration.UNSET_EVENT_ID;
866e5b51 305 long timestamp = 0;
c26d0fe0
AM
306 if (hasLost) {
307 hasLost = false;
6bdc9fac 308 EventDefinition eventDef = EventDeclaration.getLostEventDeclaration().createDefinition(streamInputReader);
c26d0fe0
AM
309 ((IntegerDefinition) eventDef.getFields().getDefinitions().get(CTFStrings.LOST_EVENTS_FIELD)).setValue(lostEventsInThisPacket);
310 ((IntegerDefinition) eventDef.getFields().getDefinitions().get(CTFStrings.LOST_EVENTS_DURATION)).setValue(lostEventsDuration);
aa572e22 311 eventDef.setTimestamp(this.lastTimestamp);
33656d8e
MK
312 return eventDef;
313 }
132a02b0 314
6bdc9fac
AM
315 final StructDefinition sehd = streamEventHeaderDef;
316 final BitBuffer currentBitBuffer = bitBuffer;
cf9a28da 317 final long posStart = currentBitBuffer.position();
1fbaecd1 318 /* Read the stream event header. */
2b7f6f09
MK
319 if (sehd != null) {
320 sehd.read(currentBitBuffer);
866e5b51 321
1fbaecd1
AM
322 /* Check for the event id. */
323 Definition idDef = sehd.lookupDefinition("id"); //$NON-NLS-1$
324 if (idDef instanceof SimpleDatatypeDefinition) {
325 eventID = ((SimpleDatatypeDefinition) idDef).getIntegerValue();
b8cb28f6 326 } else if (idDef != null) {
816fde81 327 throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
b8cb28f6 328 }
866e5b51 329
c26d0fe0
AM
330 /*
331 * Get the timestamp from the event header (may be overridden later
332 * on)
333 */
0594c61c
AM
334 IntegerDefinition timestampDef = sehd.lookupInteger("timestamp"); //$NON-NLS-1$
335 if (timestampDef != null) {
336 timestamp = calculateTimestamp(timestampDef);
6bdc9fac 337 } // else timestamp remains 0
1fbaecd1
AM
338
339 /* Check for the variant v. */
6bdc9fac
AM
340 Definition variantDef = sehd.lookupDefinition("v"); //$NON-NLS-1$
341 if (variantDef instanceof VariantDefinition) {
866e5b51 342
1fbaecd1 343 /* Get the variant current field */
6bdc9fac 344 StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
866e5b51 345
21fb02fa
MK
346 /*
347 * Try to get the id field in the current field of the variant.
348 * If it is present, it overrides the previously read event id.
349 */
6bdc9fac
AM
350 Definition idIntegerDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
351 if (idIntegerDef instanceof IntegerDefinition) {
352 eventID = ((IntegerDefinition) idIntegerDef).getValue();
21fb02fa 353 }
866e5b51 354
c26d0fe0
AM
355 /*
356 * Get the timestamp. This would overwrite any previous
357 * timestamp definition
358 */
0594c61c
AM
359 Definition def = variantCurrentField.lookupDefinition("timestamp"); //$NON-NLS-1$
360 if (def instanceof IntegerDefinition) {
361 timestamp = calculateTimestamp((IntegerDefinition) def);
6bdc9fac 362 }
21fb02fa 363 }
866e5b51
FC
364 }
365
1fbaecd1
AM
366 /* Read the stream event context. */
367 if (streamEventContextDef != null) {
368 streamEventContextDef.read(currentBitBuffer);
866e5b51
FC
369 }
370
1fbaecd1 371 /* Get the right event definition using the event id. */
7ff6d3cf 372 EventDefinition eventDef = streamInputReader.getEventDefinitions().get(eventID);
866e5b51
FC
373 if (eventDef == null) {
374 throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
375 }
376
1fbaecd1 377 /* Read the event context. */
87b60a47
MK
378 if (eventDef.getEventContext() != null) {
379 eventDef.getEventContext().read(currentBitBuffer);
866e5b51
FC
380 }
381
1fbaecd1 382 /* Read the event fields. */
aa572e22
MK
383 if (eventDef.getFields() != null) {
384 eventDef.getFields().read(currentBitBuffer);
866e5b51
FC
385 }
386
387 /*
388 * Set the event timestamp using the timestamp calculated by
389 * updateTimestamp.
390 */
aa572e22 391 eventDef.setTimestamp(timestamp);
866e5b51 392
cf9a28da
MK
393 if (posStart == currentBitBuffer.position()) {
394 throw new CTFReaderException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$
395 }
396
866e5b51
FC
397 return eventDef;
398 }
399
400 /**
401 * Calculates the timestamp value of the event, possibly using the timestamp
402 * from the last event.
403 *
404 * @param timestampDef
405 * Integer definition of the timestamp.
406 * @return The calculated timestamp value.
407 */
408 private long calculateTimestamp(IntegerDefinition timestampDef) {
409 long newval;
410 long majorasbitmask;
411 int len = timestampDef.getDeclaration().getLength();
412
413 /*
414 * If the timestamp length is 64 bits, it is a full timestamp.
415 */
416 if (timestampDef.getDeclaration().getLength() == 64) {
417 lastTimestamp = timestampDef.getValue();
418 return lastTimestamp;
419 }
420
421 /*
422 * Bit mask to keep / remove all old / new bits.
423 */
424 majorasbitmask = (1L << len) - 1;
425
426 /*
427 * If the new value is smaller than the corresponding bits of the last
428 * timestamp, we assume an overflow of the compact representation.
429 */
430 newval = timestampDef.getValue();
431 if (newval < (lastTimestamp & majorasbitmask)) {
432 newval = newval + (1L << len);
433 }
434
435 /* Keep only the high bits of the old value */
436 lastTimestamp = lastTimestamp & ~majorasbitmask;
437
438 /* Then add the low bits of the new value */
439 lastTimestamp = lastTimestamp + newval;
440
441 return lastTimestamp;
442 }
443
444 @Override
445 public Definition lookupDefinition(String lookupPath) {
866e5b51
FC
446 return null;
447 }
866e5b51 448}
This page took 0.061462 seconds and 5 git commands to generate.