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