4f82c1e7afef5941c291e2748cff64c0c3de0c03
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / ctf / core / trace / CTFStreamInputPacketReader.java
1 /*******************************************************************************
2 * Copyright (c) 2011, 2015 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:
10 * Matthew Khouzam - Initial API and implementation
11 * Simon Marchi - Initial API and implementation
12 * Patrick Tasse - Bug 470754 - Incorrect time range in CTF Lost Event
13 *******************************************************************************/
14 package org.eclipse.tracecompass.ctf.core.trace;
15
16 import java.io.IOException;
17 import java.nio.ByteBuffer;
18 import java.nio.channels.FileChannel.MapMode;
19
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.eclipse.tracecompass.ctf.core.CTFException;
23 import org.eclipse.tracecompass.ctf.core.CTFStrings;
24 import org.eclipse.tracecompass.ctf.core.event.EventDefinition;
25 import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
26 import org.eclipse.tracecompass.ctf.core.event.LostEventDeclaration;
27 import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
28 import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope;
29 import org.eclipse.tracecompass.ctf.core.event.scope.ILexicalScope;
30 import org.eclipse.tracecompass.ctf.core.event.scope.LexicalScope;
31 import org.eclipse.tracecompass.ctf.core.event.types.Definition;
32 import org.eclipse.tracecompass.ctf.core.event.types.ICompositeDefinition;
33 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
34 import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
35 import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
36 import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
37 import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
38 import org.eclipse.tracecompass.ctf.core.event.types.SimpleDatatypeDefinition;
39 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
40 import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
41 import org.eclipse.tracecompass.ctf.core.event.types.VariantDefinition;
42 import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer;
43 import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
44 import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition;
45
46 /**
47 * CTF trace packet reader. Reads the events of a packet of a trace file.
48 *
49 * @author Matthew Khouzam
50 * @author Simon Marchi
51 */
52 public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseable {
53
54 // ------------------------------------------------------------------------
55 // Attributes
56 // ------------------------------------------------------------------------
57
58 private static final int BITS_PER_BYTE = Byte.SIZE;
59
60 private static final IDefinitionScope EVENT_HEADER_SCOPE = new IDefinitionScope() {
61
62 @Override
63 public IDefinition lookupDefinition(String lookupPath) {
64 return null;
65 }
66
67 @Override
68 public ILexicalScope getScopePath() {
69 return null;
70 }
71 };
72
73 /** BitBuffer used to read the trace file. */
74 @Nullable
75 private BitBuffer fBitBuffer;
76
77 /** StreamInputReader that uses this StreamInputPacketReader. */
78 private final CTFStreamInputReader fStreamInputReader;
79
80 /** Trace packet header. */
81 private final StructDeclaration fTracePacketHeaderDecl;
82
83 /** Stream packet context definition. */
84 private final StructDeclaration fStreamPacketContextDecl;
85
86 /** Stream event header definition. */
87 private final IDeclaration fStreamEventHeaderDecl;
88
89 /** Stream event context definition. */
90 private final StructDeclaration fStreamEventContextDecl;
91
92 private ICompositeDefinition fCurrentTracePacketHeaderDef;
93 private ICompositeDefinition fCurrentStreamEventHeaderDef;
94 private ICompositeDefinition fCurrentStreamPacketContextDef;
95 /** Reference to the index entry of the current packet. */
96 private ICTFPacketDescriptor fCurrentPacket = null;
97
98 /**
99 * Last timestamp recorded.
100 *
101 * Needed to calculate the complete timestamp values for the events with
102 * compact headers.
103 */
104 private long fLastTimestamp = 0;
105
106 /** CPU id of current packet. */
107 private int fCurrentCpu = 0;
108
109 private int fLostEventsInThisPacket;
110
111 private boolean fHasLost = false;
112
113 // ------------------------------------------------------------------------
114 // Constructors
115 // ------------------------------------------------------------------------
116
117 /**
118 * Constructs a StreamInputPacketReader.
119 *
120 * @param streamInputReader
121 * The StreamInputReader to which this packet reader belongs to.
122 */
123 public CTFStreamInputPacketReader(CTFStreamInputReader streamInputReader) {
124 fStreamInputReader = streamInputReader;
125
126 /* Set the BitBuffer's byte order. */
127 ByteBuffer allocateDirect = ByteBuffer.allocateDirect(0);
128 if (allocateDirect == null) {
129 throw new IllegalStateException("Unable to allocate 0 bytes!"); //$NON-NLS-1$
130 }
131 fBitBuffer = new BitBuffer(allocateDirect);
132
133 final CTFStream currentStream = streamInputReader.getStreamInput().getStream();
134 fTracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
135 fStreamPacketContextDecl = currentStream.getPacketContextDecl();
136 fStreamEventHeaderDecl = currentStream.getEventHeaderDeclaration();
137 fStreamEventContextDecl = currentStream.getEventContextDecl();
138 }
139
140 /**
141 * Get the event context defintiion
142 *
143 * @param input
144 * the bitbuffer to read from
145 * @return an context definition, can be null
146 * @throws CTFException
147 * out of bounds exception or such
148 */
149 public StructDefinition getEventContextDefinition(@NonNull BitBuffer input) throws CTFException {
150 return fStreamEventContextDecl.createDefinition(fStreamInputReader.getStreamInput(), ILexicalScope.STREAM_EVENT_CONTEXT, input);
151 }
152
153 /**
154 * Get the packet context defintiion
155 *
156 * @param input
157 * the bitbuffer to read from
158 * @return an context definition, can be null
159 * @throws CTFException
160 * out of bounds exception or such
161 */
162 public StructDefinition getStreamPacketContextDefinition(@NonNull BitBuffer input) throws CTFException {
163 return fStreamPacketContextDecl.createDefinition(fStreamInputReader.getStreamInput(), ILexicalScope.STREAM_PACKET_CONTEXT, input);
164 }
165
166 /**
167 * Get the event header defintiion
168 *
169 * @param input
170 * the bitbuffer to read from
171 * @return an header definition, can be null
172 * @throws CTFException
173 * out of bounds exception or such
174 */
175 public StructDefinition getTracePacketHeaderDefinition(@NonNull BitBuffer input) throws CTFException {
176 return fTracePacketHeaderDecl.createDefinition(fStreamInputReader.getStreamInput().getStream().getTrace(), ILexicalScope.TRACE_PACKET_HEADER, input);
177 }
178
179 /**
180 * Dispose the StreamInputPacketReader
181 */
182 @Override
183 public void close() {
184 fBitBuffer = null;
185 }
186
187 // ------------------------------------------------------------------------
188 // Getters/Setters/Predicates
189 // ------------------------------------------------------------------------
190
191 /**
192 * Gets the current packet
193 *
194 * @return the current packet
195 */
196 ICTFPacketDescriptor getCurrentPacket() {
197 return fCurrentPacket;
198 }
199
200 /**
201 * Gets the CPU (core) number
202 *
203 * @return the CPU (core) number
204 */
205 public int getCPU() {
206 return fCurrentCpu;
207 }
208
209 @Override
210 public LexicalScope getScopePath() {
211 return ILexicalScope.PACKET;
212 }
213
214 // ------------------------------------------------------------------------
215 // Operations
216 // ------------------------------------------------------------------------
217
218 @NonNull
219 private ByteBuffer getByteBufferAt(long position, long size) throws CTFException, IOException {
220 ByteBuffer map = SafeMappedByteBuffer.map(fStreamInputReader.getFc(), MapMode.READ_ONLY, position, size);
221 if (map == null) {
222 throw new CTFIOException("Failed to allocate mapped byte buffer"); //$NON-NLS-1$
223 }
224 return map;
225 }
226
227 /**
228 * Changes the current packet to the given one.
229 *
230 * @param currentPacket
231 * The index entry of the packet to switch to.
232 * @throws CTFException
233 * If we get an error reading the packet
234 * @since 1.0
235 */
236 public void setCurrentPacket(ICTFPacketDescriptor currentPacket) throws CTFException {
237 fCurrentPacket = currentPacket;
238
239 if (fCurrentPacket != null) {
240 /*
241 * Change the map of the BitBuffer.
242 */
243 ByteBuffer bb = null;
244 try {
245 bb = getByteBufferAt(fCurrentPacket.getOffsetBytes(), (fCurrentPacket.getPacketSizeBits() + BITS_PER_BYTE - 1) / BITS_PER_BYTE);
246 } catch (IOException e) {
247 throw new CTFIOException(e.getMessage(), e);
248 }
249
250 BitBuffer bitBuffer = new BitBuffer(bb);
251 fBitBuffer = bitBuffer;
252 /*
253 * Read trace packet header.
254 */
255 if (fTracePacketHeaderDecl != null) {
256 fCurrentTracePacketHeaderDef = getTracePacketHeaderDefinition(bitBuffer);
257 }
258
259 /*
260 * Read stream packet context.
261 */
262 if (fStreamPacketContextDecl != null) {
263 fCurrentStreamPacketContextDef = getStreamPacketContextDefinition(bitBuffer);
264
265 /* Read CPU ID */
266 if (getCurrentPacket().getTarget() != null) {
267 fCurrentCpu = (int) getCurrentPacket().getTargetId();
268 }
269
270 /* Read number of lost events */
271 fLostEventsInThisPacket = (int) getCurrentPacket().getLostEvents();
272 if (fLostEventsInThisPacket != 0) {
273 fHasLost = true;
274 }
275 }
276
277 /*
278 * Use the timestamp begin of the packet as the reference for the
279 * timestamp reconstitution.
280 */
281 fLastTimestamp = Math.max(currentPacket.getTimestampBegin(), 0);
282 } else {
283 fBitBuffer = null;
284 fLastTimestamp = 0;
285 }
286 }
287
288 /**
289 * Returns whether it is possible to read any more events from this packet.
290 *
291 * @return True if it is possible to read any more events from this packet.
292 */
293 public boolean hasMoreEvents() {
294 BitBuffer bitBuffer = fBitBuffer;
295 ICTFPacketDescriptor currentPacket = fCurrentPacket;
296 if (currentPacket != null && bitBuffer != null) {
297 return fHasLost || (bitBuffer.position() < currentPacket.getContentSizeBits());
298 }
299 return false;
300 }
301
302 /**
303 * Reads the next event of the packet into the right event definition.
304 *
305 * @return The event definition containing the event data that was just
306 * read.
307 * @throws CTFException
308 * If there was a problem reading the trace
309 */
310 public EventDefinition readNextEvent() throws CTFException {
311 /* Default values for those fields */
312 // compromise since we cannot have 64 bit addressing of arrays yet.
313 int eventID = (int) IEventDeclaration.UNSET_EVENT_ID;
314 final BitBuffer currentBitBuffer = fBitBuffer;
315 final ICTFPacketDescriptor currentPacket = fCurrentPacket;
316 if (currentBitBuffer == null || currentPacket == null) {
317 return null;
318 }
319 final long posStart = currentBitBuffer.position();
320 /*
321 * Return the Lost Event after all other events in this packet.
322 */
323 if (fHasLost && posStart >= currentPacket.getContentSizeBits()) {
324 fHasLost = false;
325 IEventDeclaration lostEventDeclaration = LostEventDeclaration.INSTANCE;
326 StructDeclaration lostFields = lostEventDeclaration.getFields();
327 // this is a hard coded map, we know it's not null
328 IntegerDeclaration lostFieldsDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_FIELD);
329 if (lostFieldsDecl == null)
330 {
331 throw new IllegalStateException("Lost events count not declared!"); //$NON-NLS-1$
332 }
333 IntegerDeclaration lostEventsDurationDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_DURATION);
334 if (lostEventsDurationDecl == null) {
335 throw new IllegalStateException("Lost events duration not declared!"); //$NON-NLS-1$
336 }
337 long lostEventsTimestamp = fLastTimestamp;
338 long lostEventsDuration = currentPacket.getTimestampEnd() - lostEventsTimestamp;
339 IntegerDefinition lostDurationDef = new IntegerDefinition(lostFieldsDecl, null, CTFStrings.LOST_EVENTS_DURATION, lostEventsDuration);
340 IntegerDefinition lostCountDef = new IntegerDefinition(lostEventsDurationDecl, null, CTFStrings.LOST_EVENTS_FIELD, fLostEventsInThisPacket);
341 IntegerDefinition[] fields = new IntegerDefinition[] { lostCountDef, lostDurationDef };
342 return new EventDefinition(
343 lostEventDeclaration,
344 fStreamInputReader,
345 lostEventsTimestamp,
346 null,
347 null,
348 null,
349 new StructDefinition(
350 lostFields,
351 this, "fields", //$NON-NLS-1$
352 fields
353 ));
354
355 }
356
357 /* Read the stream event header. */
358 if (fStreamEventHeaderDecl != null) {
359 if (fStreamEventHeaderDecl instanceof IEventHeaderDeclaration) {
360 fCurrentStreamEventHeaderDef = (ICompositeDefinition) fStreamEventHeaderDecl.createDefinition(EVENT_HEADER_SCOPE, "", currentBitBuffer); //$NON-NLS-1$
361 EventHeaderDefinition ehd = (EventHeaderDefinition) fCurrentStreamEventHeaderDef;
362 eventID = ehd.getId();
363 } else {
364 fCurrentStreamEventHeaderDef = ((StructDeclaration) fStreamEventHeaderDecl).createDefinition(EVENT_HEADER_SCOPE, ILexicalScope.EVENT_HEADER, currentBitBuffer);
365 StructDefinition StructEventHeaderDef = (StructDefinition) fCurrentStreamEventHeaderDef;
366 /* Check for the event id. */
367 IDefinition idDef = StructEventHeaderDef.lookupDefinition("id"); //$NON-NLS-1$
368 SimpleDatatypeDefinition simpleIdDef = null;
369 if (idDef instanceof SimpleDatatypeDefinition) {
370 simpleIdDef = ((SimpleDatatypeDefinition) idDef);
371 } else if (idDef != null) {
372 throw new CTFIOException("Id defintion not an integer, enum or float definiton in event header."); //$NON-NLS-1$
373 }
374 /* Check for the variant v. */
375 IDefinition variantDef = StructEventHeaderDef.lookupDefinition("v"); //$NON-NLS-1$
376 if (variantDef instanceof VariantDefinition) {
377
378 /* Get the variant current field */
379 StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
380
381 /*
382 * Try to get the id field in the current field of the
383 * variant. If it is present, it overrides the previously
384 * read event id.
385 */
386 IDefinition vIdDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
387 if (vIdDef instanceof IntegerDefinition) {
388 simpleIdDef = (SimpleDatatypeDefinition) vIdDef;
389 }
390
391 }
392 if (simpleIdDef != null) {
393 eventID = simpleIdDef.getIntegerValue().intValue();
394 }
395 }
396 }
397 /* Get the right event definition using the event id. */
398 EventDeclaration eventDeclaration = (EventDeclaration) fStreamInputReader.getStreamInput().getStream().getEventDeclaration(eventID);
399 if (eventDeclaration == null) {
400 throw new CTFIOException("Incorrect event id : " + eventID); //$NON-NLS-1$
401 }
402 EventDefinition eventDef = eventDeclaration.createDefinition(fStreamInputReader, fCurrentStreamEventHeaderDef, currentBitBuffer, fLastTimestamp);
403 fLastTimestamp = eventDef.getTimestamp();
404 /*
405 * Set the event timestamp using the timestamp calculated by
406 * updateTimestamp.
407 */
408
409 if (posStart == currentBitBuffer.position()) {
410 throw new CTFIOException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$
411 }
412
413 return eventDef;
414 }
415
416 @Override
417 public Definition lookupDefinition(String lookupPath) {
418 if (lookupPath.equals(ILexicalScope.STREAM_PACKET_CONTEXT.getPath())) {
419 return (Definition) fCurrentStreamPacketContextDef;
420 }
421 if (lookupPath.equals(ILexicalScope.TRACE_PACKET_HEADER.getPath())) {
422 return (Definition) fCurrentTracePacketHeaderDef;
423 }
424 return null;
425 }
426
427
428 /**
429 * Get stream event header
430 *
431 * @return the stream event header
432 */
433 public ICompositeDefinition getStreamEventHeaderDefinition() {
434 return fCurrentStreamEventHeaderDef;
435 }
436
437 /**
438 * Get the current packet event header
439 *
440 * @return the current packet event header
441 */
442 public StructDefinition getCurrentPacketEventHeader() {
443 if (fCurrentTracePacketHeaderDef instanceof StructDefinition) {
444 return (StructDefinition) fCurrentTracePacketHeaderDef;
445 }
446 return null;
447 }
448 }
This page took 0.063297 seconds and 4 git commands to generate.