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