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