tmf/lttng: Update 2014 copyrights
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / StreamInputPacketReader.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 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 45 /** BitBuffer used to read the trace file. */
2882273c 46 private final BitBuffer fBitBuffer;
866e5b51 47
6bdc9fac 48 /** StreamInputReader that uses this StreamInputPacketReader. */
2882273c 49 private final StreamInputReader fStreamInputReader;
866e5b51 50
6bdc9fac 51 /** Trace packet header. */
2882273c 52 private final StructDefinition fTracePacketHeaderDef;
866e5b51 53
6bdc9fac 54 /** Stream packet context definition. */
2882273c 55 private final StructDefinition fStreamPacketContextDef;
866e5b51 56
6bdc9fac 57 /** Stream event header definition. */
2882273c 58 private final StructDefinition fStreamEventHeaderDef;
866e5b51 59
c26d0fe0 60 /** Stream event context definition. */
2882273c 61 private final StructDefinition fStreamEventContextDef;
866e5b51 62
6bdc9fac 63 /** Reference to the index entry of the current packet. */
2882273c 64 private StreamInputPacketIndexEntry fCurrentPacket = null;
6bdc9fac 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 */
2882273c 72 private long fLastTimestamp = 0;
6bdc9fac
AM
73
74 /** CPU id of current packet. */
2882273c 75 private int fCurrentCpu = 0;
866e5b51 76
2882273c 77 private int fLostEventsInThisPacket;
5c7202b5 78
2882273c 79 private long fLostEventsDuration;
c26d0fe0 80
2882273c 81 private boolean fHasLost = false;
c26d0fe0 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) {
2882273c 94 fStreamInputReader = streamInputReader;
866e5b51 95
6bdc9fac 96 /* Set the BitBuffer's byte order. */
2882273c
MK
97 fBitBuffer = new BitBuffer();
98 fBitBuffer.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) {
2882273c 104 fTracePacketHeaderDef = tracePacketHeaderDecl.createDefinition(this, "trace.packet.header"); //$NON-NLS-1$
6bdc9fac 105 } else {
2882273c 106 fTracePacketHeaderDef = null;
6bdc9fac
AM
107 }
108
109 /* Create stream packet context definition. */
110 StructDeclaration streamPacketContextDecl = currentStream.getPacketContextDecl();
111 if (streamPacketContextDecl != null) {
2882273c 112 fStreamPacketContextDef = streamPacketContextDecl.createDefinition(this, "stream.packet.context"); //$NON-NLS-1$
6bdc9fac 113 } else {
2882273c 114 fStreamPacketContextDef = null;
6bdc9fac
AM
115 }
116
117 /* Create stream event header definition. */
118 StructDeclaration streamEventHeaderDecl = currentStream.getEventHeaderDecl();
119 if (streamEventHeaderDecl != null) {
2882273c 120 fStreamEventHeaderDef = streamEventHeaderDecl.createDefinition(this, "stream.event.header"); //$NON-NLS-1$
6bdc9fac 121 } else {
2882273c 122 fStreamEventHeaderDef = null;
6bdc9fac
AM
123 }
124
125 /* Create stream event context definition. */
126 StructDeclaration streamEventContextDecl = currentStream.getEventContextDecl();
127 if (streamEventContextDecl != null) {
2882273c 128 fStreamEventContextDef = streamEventContextDecl.createDefinition(this, "stream.event.context"); //$NON-NLS-1$
6bdc9fac 129 } else {
2882273c 130 fStreamEventContextDef = null;
6bdc9fac
AM
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() {
2882273c 150 fBitBuffer.setByteBuffer(null);
5d1c6919
PT
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() {
2882273c 163 return fCurrentPacket;
866e5b51
FC
164 }
165
9ac2eb62
MK
166 /**
167 * Gets the steamPacketContext Definition
168 *
169 * @return steamPacketContext Definition
170 */
866e5b51 171 public StructDefinition getStreamPacketContextDef() {
2882273c 172 return fStreamPacketContextDef;
866e5b51
FC
173 }
174
45cbd8dc
AM
175 /**
176 * Gets the stream's event context definition.
177 *
178 * @return The streamEventContext definition
179 */
180 public StructDefinition getStreamEventContextDef() {
2882273c 181 return fStreamEventContextDef;
45cbd8dc
AM
182 }
183
9ac2eb62
MK
184 /**
185 * Gets the CPU (core) number
186 *
187 * @return the CPU (core) number
188 */
866e5b51 189 public int getCPU() {
2882273c 190 return fCurrentCpu;
866e5b51
FC
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;
2882273c 212 fCurrentPacket = currentPacket;
866e5b51 213
2882273c 214 if (fCurrentPacket != null) {
866e5b51
FC
215 /*
216 * Change the map of the BitBuffer.
217 */
526c823c 218 ByteBuffer bb = null;
866e5b51 219 try {
2882273c
MK
220 bb = fStreamInputReader.getStreamInput().getByteBufferAt(
221 fCurrentPacket.getOffsetBytes(),
222 (fCurrentPacket.getPacketSizeBits() + 7) / 8);
866e5b51 223 } catch (IOException e) {
cf9a28da 224 throw new CTFReaderException(e.getMessage(), e);
866e5b51
FC
225 }
226
2882273c 227 fBitBuffer.setByteBuffer(bb);
866e5b51
FC
228
229 /*
230 * Read trace packet header.
231 */
2882273c
MK
232 if (fTracePacketHeaderDef != null) {
233 fTracePacketHeaderDef.read(fBitBuffer);
866e5b51
FC
234 }
235
236 /*
237 * Read stream packet context.
238 */
239 if (getStreamPacketContextDef() != null) {
2882273c 240 getStreamPacketContextDef().read(fBitBuffer);
33656d8e 241
132a02b0 242 /* Read CPU ID */
2882273c
MK
243 if (getCurrentPacket().getTarget() != null) {
244 fCurrentCpu = (int) getCurrentPacket().getTargetId();
866e5b51 245 }
21fb02fa 246
132a02b0 247 /* Read number of lost events */
2882273c
MK
248 fLostEventsInThisPacket = (int) getCurrentPacket().getLostEvents();
249 if (fLostEventsInThisPacket != 0) {
250 fHasLost = true;
c26d0fe0
AM
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;
2882273c 257 int index = fStreamInputReader.getStreamInput().getIndex().getEntries().indexOf(currentPacket);
c26d0fe0
AM
258 if (index == 0) {
259 lostEventsStartTime = currentPacket.getTimestampBegin() + 1;
260 } else {
2882273c 261 prevPacket = fStreamInputReader.getStreamInput().getIndex().getEntries().get(index - 1);
c26d0fe0
AM
262 lostEventsStartTime = prevPacket.getTimestampEnd();
263 }
2882273c 264 fLostEventsDuration = Math.abs(lostEventsStartTime - currentPacket.getTimestampBegin());
c26d0fe0 265 }
866e5b51
FC
266 }
267
268 /*
269 * Use the timestamp begin of the packet as the reference for the
270 * timestamp reconstitution.
271 */
2882273c 272 fLastTimestamp = currentPacket.getTimestampBegin();
866e5b51 273 } else {
2882273c 274 fBitBuffer.setByteBuffer(null);
866e5b51 275
2882273c 276 fLastTimestamp = 0;
866e5b51
FC
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() {
2882273c
MK
286 if (fCurrentPacket != null) {
287 return fHasLost || (fBitBuffer.position() < fCurrentPacket.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;
2882273c
MK
304 if (fHasLost) {
305 fHasLost = false;
306 EventDefinition eventDef = EventDeclaration.getLostEventDeclaration().createDefinition(fStreamInputReader);
307 ((IntegerDefinition) eventDef.getFields().getDefinitions().get(CTFStrings.LOST_EVENTS_FIELD)).setValue(fLostEventsInThisPacket);
308 ((IntegerDefinition) eventDef.getFields().getDefinitions().get(CTFStrings.LOST_EVENTS_DURATION)).setValue(fLostEventsDuration);
309 eventDef.setTimestamp(fLastTimestamp);
33656d8e
MK
310 return eventDef;
311 }
132a02b0 312
2882273c
MK
313 final StructDefinition sehd = fStreamEventHeaderDef;
314 final BitBuffer currentBitBuffer = fBitBuffer;
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 364 /* Read the stream event context. */
2882273c
MK
365 if (fStreamEventContextDef != null) {
366 fStreamEventContextDef.read(currentBitBuffer);
866e5b51
FC
367 }
368
1fbaecd1 369 /* Get the right event definition using the event id. */
2882273c 370 EventDefinition eventDef = fStreamInputReader.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) {
2882273c
MK
415 fLastTimestamp = timestampDef.getValue();
416 return fLastTimestamp;
866e5b51
FC
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();
2882273c 429 if (newval < (fLastTimestamp & majorasbitmask)) {
866e5b51
FC
430 newval = newval + (1L << len);
431 }
432
433 /* Keep only the high bits of the old value */
2882273c 434 fLastTimestamp = fLastTimestamp & ~majorasbitmask;
866e5b51
FC
435
436 /* Then add the low bits of the new value */
2882273c 437 fLastTimestamp = fLastTimestamp + newval;
866e5b51 438
2882273c 439 return fLastTimestamp;
866e5b51
FC
440 }
441
442 @Override
443 public Definition lookupDefinition(String lookupPath) {
866e5b51
FC
444 return null;
445 }
866e5b51 446}
This page took 0.062612 seconds and 5 git commands to generate.