969bd498829e95d278a5940e3518cae7138afb71
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / StreamInputPacketReader.java
1 /*******************************************************************************
2 * Copyright (c) 2011-2013 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 import java.util.Collection;
17
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.types.Definition;
23 import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
24 import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
25 import org.eclipse.linuxtools.ctf.core.event.types.SimpleDatatypeDefinition;
26 import org.eclipse.linuxtools.ctf.core.event.types.StructDeclaration;
27 import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
28 import org.eclipse.linuxtools.ctf.core.event.types.VariantDefinition;
29 import org.eclipse.linuxtools.internal.ctf.core.event.EventDeclaration;
30 import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
31
32 /**
33 * CTF trace packet reader. Reads the events of a packet of a trace file.
34 *
35 * @version 1.0
36 * @author Matthew Khouzam
37 * @author Simon Marchi
38 */
39 public class StreamInputPacketReader implements IDefinitionScope {
40
41 // ------------------------------------------------------------------------
42 // Attributes
43 // ------------------------------------------------------------------------
44
45 /** BitBuffer used to read the trace file. */
46 private final BitBuffer fBitBuffer;
47
48 /** StreamInputReader that uses this StreamInputPacketReader. */
49 private final StreamInputReader fStreamInputReader;
50
51 /** Trace packet header. */
52 private final StructDefinition fTracePacketHeaderDef;
53
54 /** Stream packet context definition. */
55 private final StructDefinition fStreamPacketContextDef;
56
57 /** Stream event header definition. */
58 private final StructDefinition fStreamEventHeaderDef;
59
60 /** Stream event context definition. */
61 private final StructDefinition fStreamEventContextDef;
62
63 /** Reference to the index entry of the current packet. */
64 private StreamInputPacketIndexEntry fCurrentPacket = null;
65
66 /**
67 * Last timestamp recorded.
68 *
69 * Needed to calculate the complete timestamp values for the events with
70 * compact headers.
71 */
72 private long fLastTimestamp = 0;
73
74 /** CPU id of current packet. */
75 private int fCurrentCpu = 0;
76
77 private int fLostEventsInThisPacket;
78
79 private long fLostEventsDuration;
80
81 private boolean fHasLost = false;
82
83 // ------------------------------------------------------------------------
84 // Constructors
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 fStreamInputReader = streamInputReader;
95
96 /* Set the BitBuffer's byte order. */
97 fBitBuffer = new BitBuffer();
98 fBitBuffer.setByteOrder(streamInputReader.getByteOrder());
99
100 /* Create trace packet header definition. */
101 final Stream currentStream = streamInputReader.getStreamInput().getStream();
102 StructDeclaration tracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
103 if (tracePacketHeaderDecl != null) {
104 fTracePacketHeaderDef = tracePacketHeaderDecl.createDefinition(this, "trace.packet.header"); //$NON-NLS-1$
105 } else {
106 fTracePacketHeaderDef = null;
107 }
108
109 /* Create stream packet context definition. */
110 StructDeclaration streamPacketContextDecl = currentStream.getPacketContextDecl();
111 if (streamPacketContextDecl != null) {
112 fStreamPacketContextDef = streamPacketContextDecl.createDefinition(this, "stream.packet.context"); //$NON-NLS-1$
113 } else {
114 fStreamPacketContextDef = null;
115 }
116
117 /* Create stream event header definition. */
118 StructDeclaration streamEventHeaderDecl = currentStream.getEventHeaderDecl();
119 if (streamEventHeaderDecl != null) {
120 fStreamEventHeaderDef = streamEventHeaderDecl.createDefinition(this, "stream.event.header"); //$NON-NLS-1$
121 } else {
122 fStreamEventHeaderDef = null;
123 }
124
125 /* Create stream event context definition. */
126 StructDeclaration streamEventContextDecl = currentStream.getEventContextDecl();
127 if (streamEventContextDecl != null) {
128 fStreamEventContextDef = streamEventContextDecl.createDefinition(this, "stream.event.context"); //$NON-NLS-1$
129 } else {
130 fStreamEventContextDef = null;
131 }
132
133 /* Create event definitions */
134 Collection<IEventDeclaration> eventDecls = streamInputReader.getStreamInput().getStream().getEvents().values();
135
136 for (IEventDeclaration event : eventDecls) {
137 if (!streamInputReader.getEventDefinitions().containsKey(event.getId())) {
138 EventDefinition eventDef = event.createDefinition(streamInputReader);
139 streamInputReader.addEventDefinition(event.getId(), eventDef);
140 }
141 }
142 }
143
144 /**
145 * Dispose the StreamInputPacketReader
146 *
147 * @since 2.0
148 */
149 public void dispose() {
150 fBitBuffer.setByteBuffer(null);
151 }
152
153 // ------------------------------------------------------------------------
154 // Getters/Setters/Predicates
155 // ------------------------------------------------------------------------
156
157 /**
158 * Gets the current packet
159 *
160 * @return the current packet
161 */
162 StreamInputPacketIndexEntry getCurrentPacket() {
163 return fCurrentPacket;
164 }
165
166 /**
167 * Gets the steamPacketContext Definition
168 *
169 * @return steamPacketContext Definition
170 */
171 public StructDefinition getStreamPacketContextDef() {
172 return fStreamPacketContextDef;
173 }
174
175 /**
176 * Gets the stream's event context definition.
177 *
178 * @return The streamEventContext definition
179 */
180 public StructDefinition getStreamEventContextDef() {
181 return fStreamEventContextDef;
182 }
183
184 /**
185 * Gets the CPU (core) number
186 *
187 * @return the CPU (core) number
188 */
189 public int getCPU() {
190 return fCurrentCpu;
191 }
192
193 @Override
194 public String getPath() {
195 return ""; //$NON-NLS-1$
196 }
197
198 // ------------------------------------------------------------------------
199 // Operations
200 // ------------------------------------------------------------------------
201
202 /**
203 * Changes the current packet to the given one.
204 *
205 * @param currentPacket
206 * The index entry of the packet to switch to.
207 * @throws CTFReaderException
208 * If we get an error reading the packet
209 */
210 void setCurrentPacket(StreamInputPacketIndexEntry currentPacket) throws CTFReaderException {
211 StreamInputPacketIndexEntry prevPacket = null;
212 fCurrentPacket = currentPacket;
213
214 if (fCurrentPacket != null) {
215 /*
216 * Change the map of the BitBuffer.
217 */
218 ByteBuffer bb = null;
219 try {
220 bb = fStreamInputReader.getStreamInput().getByteBufferAt(
221 fCurrentPacket.getOffsetBytes(),
222 (fCurrentPacket.getPacketSizeBits() + 7) / 8);
223 } catch (IOException e) {
224 throw new CTFReaderException(e.getMessage(), e);
225 }
226
227 fBitBuffer.setByteBuffer(bb);
228
229 /*
230 * Read trace packet header.
231 */
232 if (fTracePacketHeaderDef != null) {
233 fTracePacketHeaderDef.read(fBitBuffer);
234 }
235
236 /*
237 * Read stream packet context.
238 */
239 if (getStreamPacketContextDef() != null) {
240 getStreamPacketContextDef().read(fBitBuffer);
241
242 /* Read CPU ID */
243 if (getCurrentPacket().getTarget() != null) {
244 fCurrentCpu = (int) getCurrentPacket().getTargetId();
245 }
246
247 /* Read number of lost events */
248 fLostEventsInThisPacket = (int) getCurrentPacket().getLostEvents();
249 if (fLostEventsInThisPacket != 0) {
250 fHasLost = 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 = fStreamInputReader.getStreamInput().getIndex().getEntries().indexOf(currentPacket);
258 if (index == 0) {
259 lostEventsStartTime = currentPacket.getTimestampBegin() + 1;
260 } else {
261 prevPacket = fStreamInputReader.getStreamInput().getIndex().getEntries().get(index - 1);
262 lostEventsStartTime = prevPacket.getTimestampEnd();
263 }
264 fLostEventsDuration = Math.abs(lostEventsStartTime - currentPacket.getTimestampBegin());
265 }
266 }
267
268 /*
269 * Use the timestamp begin of the packet as the reference for the
270 * timestamp reconstitution.
271 */
272 fLastTimestamp = currentPacket.getTimestampBegin();
273 } else {
274 fBitBuffer.setByteBuffer(null);
275
276 fLastTimestamp = 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 (fCurrentPacket != null) {
287 return fHasLost || (fBitBuffer.position() < fCurrentPacket.getContentSizeBits());
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
298 * If there was a problem reading the trace
299 */
300 public EventDefinition readNextEvent() throws CTFReaderException {
301 /* Default values for those fields */
302 long eventID = EventDeclaration.UNSET_EVENT_ID;
303 long timestamp = 0;
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);
310 return eventDef;
311 }
312
313 final StructDefinition sehd = fStreamEventHeaderDef;
314 final BitBuffer currentBitBuffer = fBitBuffer;
315 final long posStart = currentBitBuffer.position();
316 /* Read the stream event header. */
317 if (sehd != null) {
318 sehd.read(currentBitBuffer);
319
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();
324 } else if (idDef != null) {
325 throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
326 }
327
328 /*
329 * Get the timestamp from the event header (may be overridden later
330 * on)
331 */
332 IntegerDefinition timestampDef = sehd.lookupInteger("timestamp"); //$NON-NLS-1$
333 if (timestampDef != null) {
334 timestamp = calculateTimestamp(timestampDef);
335 } // else timestamp remains 0
336
337 /* Check for the variant v. */
338 Definition variantDef = sehd.lookupDefinition("v"); //$NON-NLS-1$
339 if (variantDef instanceof VariantDefinition) {
340
341 /* Get the variant current field */
342 StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
343
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 */
348 Definition idIntegerDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
349 if (idIntegerDef instanceof IntegerDefinition) {
350 eventID = ((IntegerDefinition) idIntegerDef).getValue();
351 }
352
353 /*
354 * Get the timestamp. This would overwrite any previous
355 * timestamp definition
356 */
357 Definition def = variantCurrentField.lookupDefinition("timestamp"); //$NON-NLS-1$
358 if (def instanceof IntegerDefinition) {
359 timestamp = calculateTimestamp((IntegerDefinition) def);
360 }
361 }
362 }
363
364 /* Read the stream event context. */
365 if (fStreamEventContextDef != null) {
366 fStreamEventContextDef.read(currentBitBuffer);
367 }
368
369 /* Get the right event definition using the event id. */
370 EventDefinition eventDef = fStreamInputReader.getEventDefinitions().get(eventID);
371 if (eventDef == null) {
372 throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
373 }
374
375 /* Read the event context. */
376 if (eventDef.getEventContext() != null) {
377 eventDef.getEventContext().read(currentBitBuffer);
378 }
379
380 /* Read the event fields. */
381 if (eventDef.getFields() != null) {
382 eventDef.getFields().read(currentBitBuffer);
383 }
384
385 /*
386 * Set the event timestamp using the timestamp calculated by
387 * updateTimestamp.
388 */
389 eventDef.setTimestamp(timestamp);
390
391 if (posStart == currentBitBuffer.position()) {
392 throw new CTFReaderException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$
393 }
394
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 fLastTimestamp = timestampDef.getValue();
416 return fLastTimestamp;
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 < (fLastTimestamp & majorasbitmask)) {
430 newval = newval + (1L << len);
431 }
432
433 /* Keep only the high bits of the old value */
434 fLastTimestamp = fLastTimestamp & ~majorasbitmask;
435
436 /* Then add the low bits of the new value */
437 fLastTimestamp = fLastTimestamp + newval;
438
439 return fLastTimestamp;
440 }
441
442 @Override
443 public Definition lookupDefinition(String lookupPath) {
444 return null;
445 }
446 }
This page took 0.044451 seconds and 4 git commands to generate.