tmf: Correctly export all packages in runtime plugins
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / ctf / core / trace / StreamInputPacketReader.java
CommitLineData
866e5b51
FC
1/*******************************************************************************
2 * Copyright (c) 2011-2012 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 *******************************************************************************/
12package org.eclipse.linuxtools.ctf.core.trace;
13
14import java.io.IOException;
15import java.nio.MappedByteBuffer;
16import java.nio.channels.FileChannel.MapMode;
17import java.util.Collection;
18import java.util.HashMap;
19
20import org.eclipse.linuxtools.ctf.core.event.EventDeclaration;
21import org.eclipse.linuxtools.ctf.core.event.EventDefinition;
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;
ce2388e0
FC
29import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
30import org.eclipse.linuxtools.internal.ctf.core.trace.Stream;
31import org.eclipse.linuxtools.internal.ctf.core.trace.StreamInputPacketIndexEntry;
866e5b51
FC
32
33/**
d37aaa7f 34 * CTF trace packet reader. Reads the events of a packet of a trace file.
5c7202b5 35 *
d37aaa7f
FC
36 * @version 1.0
37 * @author Matthew Khouzam
38 * @author Simon Marchi
866e5b51 39 */
bfe038ff 40public class StreamInputPacketReader implements IDefinitionScope {
866e5b51
FC
41
42 // ------------------------------------------------------------------------
6bdc9fac 43 // Attributes
866e5b51
FC
44 // ------------------------------------------------------------------------
45
6bdc9fac
AM
46 /** BitBuffer used to read the trace file. */
47 private final BitBuffer bitBuffer;
866e5b51 48
6bdc9fac 49 /** StreamInputReader that uses this StreamInputPacketReader. */
866e5b51
FC
50 private final StreamInputReader streamInputReader;
51
6bdc9fac
AM
52 /** Trace packet header. */
53 private final StructDefinition tracePacketHeaderDef;
866e5b51 54
6bdc9fac
AM
55 /** Stream packet context definition. */
56 private final StructDefinition streamPacketContextDef;
866e5b51 57
6bdc9fac
AM
58 /** Stream event header definition. */
59 private final StructDefinition streamEventHeaderDef;
866e5b51 60
6bdc9fac
AM
61 /** Stream event context definition.*/
62 private final StructDefinition streamEventContextDef;
866e5b51 63
6bdc9fac 64 /** Maps event ID to event definitions. */
788ddcbc 65 private final HashMap<Long, EventDefinition> events;
866e5b51 66
6bdc9fac
AM
67 /** Reference to the index entry of the current packet. */
68 private StreamInputPacketIndexEntry currentPacket = null;
69
866e5b51 70 /**
6bdc9fac
AM
71 * Last timestamp recorded.
72 *
73 * Needed to calculate the complete timestamp values for the events with
74 * compact headers.
866e5b51 75 */
6bdc9fac
AM
76 private long lastTimestamp = 0;
77
78 /** CPU id of current packet. */
866e5b51
FC
79 private int currentCpu = 0;
80
6bdc9fac 81 /** number of lost events in this packet */
33656d8e
MK
82 private int lostSoFar;
83
5c7202b5
MK
84 private int lostEventsInThisPacket;
85
866e5b51 86 // ------------------------------------------------------------------------
6bdc9fac 87 // Constructors
866e5b51
FC
88 // ------------------------------------------------------------------------
89
90 /**
91 * Constructs a StreamInputPacketReader.
92 *
93 * @param streamInputReader
94 * The StreamInputReader to which this packet reader belongs to.
95 */
96 public StreamInputPacketReader(StreamInputReader streamInputReader) {
97 this.streamInputReader = streamInputReader;
98
6bdc9fac
AM
99 /* Set the BitBuffer's byte order. */
100 bitBuffer = new BitBuffer();
101 bitBuffer.setByteOrder(streamInputReader.getByteOrder());
33656d8e 102
6bdc9fac 103 events = streamInputReader.getStreamInput().getStream().getTrace().getEventDefs(streamInputReader.getStreamInput());
788ddcbc 104 lostSoFar = 0;
866e5b51 105
6bdc9fac
AM
106 /* Create trace packet header definition. */
107 final Stream currentStream = streamInputReader.getStreamInput().getStream();
108 StructDeclaration tracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
109 if (tracePacketHeaderDecl != null) {
110 tracePacketHeaderDef = tracePacketHeaderDecl.createDefinition(this, "trace.packet.header"); //$NON-NLS-1$
111 } else {
112 tracePacketHeaderDef = null;
113 }
114
115 /* Create stream packet context definition. */
116 StructDeclaration streamPacketContextDecl = currentStream.getPacketContextDecl();
117 if (streamPacketContextDecl != null) {
118 streamPacketContextDef = streamPacketContextDecl.createDefinition(this, "stream.packet.context"); //$NON-NLS-1$
119 } else {
120 streamPacketContextDef = null;
121 }
122
123 /* Create stream event header definition. */
124 StructDeclaration streamEventHeaderDecl = currentStream.getEventHeaderDecl();
125 if (streamEventHeaderDecl != null) {
126 streamEventHeaderDef = streamEventHeaderDecl.createDefinition(this, "stream.event.header"); //$NON-NLS-1$
127 } else {
128 streamEventHeaderDef = null;
129 }
130
131 /* Create stream event context definition. */
132 StructDeclaration streamEventContextDecl = currentStream.getEventContextDecl();
133 if (streamEventContextDecl != null) {
134 streamEventContextDef = streamEventContextDecl.createDefinition(this, "stream.event.context"); //$NON-NLS-1$
135 } else {
136 streamEventContextDef = null;
137 }
138
139 /* Create event definitions */
140 Collection<EventDeclaration> eventDecls = streamInputReader.getStreamInput().getStream().getEvents().values();
141
142 for (EventDeclaration event : eventDecls) {
143 if (!events.containsKey(event.getId())) {
144 EventDefinition eventDef = event.createDefinition(streamInputReader);
145 events.put(event.getId(), eventDef);
146 }
147 }
148 }
866e5b51
FC
149
150 // ------------------------------------------------------------------------
151 // Getters/Setters/Predicates
152 // ------------------------------------------------------------------------
153
9ac2eb62
MK
154 /**
155 * Gets the current packet
156 *
157 * @return the current packet
158 */
866e5b51
FC
159 public StreamInputPacketIndexEntry getCurrentPacket() {
160 return this.currentPacket;
161 }
162
9ac2eb62
MK
163 /**
164 * Gets the steamPacketContext Definition
165 *
166 * @return steamPacketContext Definition
167 */
866e5b51
FC
168 public StructDefinition getStreamPacketContextDef() {
169 return this.streamPacketContextDef;
170 }
171
45cbd8dc
AM
172 /**
173 * Gets the stream's event context definition.
174 *
175 * @return The streamEventContext definition
176 */
177 public StructDefinition getStreamEventContextDef() {
178 return streamEventContextDef;
179 }
180
9ac2eb62
MK
181 /**
182 * Gets the CPU (core) number
183 *
184 * @return the CPU (core) number
185 */
866e5b51
FC
186 public int getCPU() {
187 return this.currentCpu;
188 }
189
190 @Override
191 public String getPath() {
192 return ""; //$NON-NLS-1$
193 }
194
195 // ------------------------------------------------------------------------
196 // Operations
197 // ------------------------------------------------------------------------
198
866e5b51
FC
199 /**
200 * Changes the current packet to the given one.
201 *
202 * @param currentPacket
203 * The index entry of the packet to switch to.
204 */
205 public void setCurrentPacket(StreamInputPacketIndexEntry currentPacket) {
206 this.currentPacket = currentPacket;
207
208 if (this.currentPacket != null) {
209 /*
210 * Change the map of the BitBuffer.
211 */
212 MappedByteBuffer bb = null;
213 try {
6bdc9fac 214 bb = streamInputReader.getStreamInput().getFileChannel()
788ddcbc
MK
215 .map(MapMode.READ_ONLY,
216 this.currentPacket.getOffsetBytes(),
217 (this.currentPacket.getPacketSizeBits() + 7) / 8);
866e5b51
FC
218 } catch (IOException e) {
219 /*
220 * The streamInputReader object is already allocated, so this
221 * shouldn't fail bar some very bad kernel or RAM errors...
222 */
223 e.printStackTrace();
224 }
225
6bdc9fac 226 bitBuffer.setByteBuffer(bb);
866e5b51
FC
227
228 /*
229 * Read trace packet header.
230 */
6bdc9fac
AM
231 if (tracePacketHeaderDef != null) {
232 tracePacketHeaderDef.read(bitBuffer);
866e5b51
FC
233 }
234
235 /*
236 * Read stream packet context.
237 */
238 if (getStreamPacketContextDef() != null) {
6bdc9fac 239 getStreamPacketContextDef().read(bitBuffer);
33656d8e 240
132a02b0 241 /* Read CPU ID */
21fb02fa 242 if (this.getCurrentPacket().getTarget() != null) {
132a02b0 243 this.currentCpu = (int) this.getCurrentPacket().getTargetId();
866e5b51 244 }
21fb02fa 245
132a02b0
MK
246 /* Read number of lost events */
247 lostEventsInThisPacket = (int) this.getCurrentPacket().getLostEvents();
21fb02fa
MK
248 lostSoFar = 0;
249
866e5b51
FC
250 }
251
252 /*
253 * Use the timestamp begin of the packet as the reference for the
254 * timestamp reconstitution.
255 */
ce2388e0 256 lastTimestamp = currentPacket.getTimestampBegin();
866e5b51 257 } else {
6bdc9fac 258 bitBuffer.setByteBuffer(null);
866e5b51
FC
259
260 lastTimestamp = 0;
261 }
262 }
263
264 /**
265 * Returns whether it is possible to read any more events from this packet.
266 *
267 * @return True if it is possible to read any more events from this packet.
268 */
269 public boolean hasMoreEvents() {
270 if (currentPacket != null) {
6bdc9fac 271 return bitBuffer.position() < currentPacket.getContentSizeBits();
866e5b51
FC
272 }
273 return false;
274 }
275
276 /**
277 * Reads the next event of the packet into the right event definition.
278 *
279 * @return The event definition containing the event data that was just
280 * read.
281 * @throws CTFReaderException
be6df2d8 282 * If there was a problem reading the trace
866e5b51
FC
283 */
284 public EventDefinition readNextEvent() throws CTFReaderException {
1fbaecd1
AM
285 /* Default values for those fields */
286 long eventID = 0;
866e5b51
FC
287 long timestamp = 0;
288
5c7202b5 289 if (lostEventsInThisPacket > lostSoFar) {
6bdc9fac 290 EventDefinition eventDef = EventDeclaration.getLostEventDeclaration().createDefinition(streamInputReader);
aa572e22 291 eventDef.setTimestamp(this.lastTimestamp);
33656d8e
MK
292 ++lostSoFar;
293 return eventDef;
294 }
132a02b0 295
6bdc9fac
AM
296 final StructDefinition sehd = streamEventHeaderDef;
297 final BitBuffer currentBitBuffer = bitBuffer;
2b7f6f09 298
1fbaecd1 299 /* Read the stream event header. */
2b7f6f09
MK
300 if (sehd != null) {
301 sehd.read(currentBitBuffer);
866e5b51 302
1fbaecd1
AM
303 /* Check for the event id. */
304 Definition idDef = sehd.lookupDefinition("id"); //$NON-NLS-1$
305 if (idDef instanceof SimpleDatatypeDefinition) {
306 eventID = ((SimpleDatatypeDefinition) idDef).getIntegerValue();
307 } // else, eventID remains 0
866e5b51 308
1fbaecd1
AM
309 /* Get the timestamp from the event header (may be overridden later on) */
310 Definition timestampDef = sehd.lookupInteger("timestamp"); //$NON-NLS-1$
6bdc9fac
AM
311 if (timestampDef instanceof IntegerDefinition) {
312 timestamp = calculateTimestamp((IntegerDefinition) timestampDef);
313 } // else timestamp remains 0
1fbaecd1
AM
314
315 /* Check for the variant v. */
6bdc9fac
AM
316 Definition variantDef = sehd.lookupDefinition("v"); //$NON-NLS-1$
317 if (variantDef instanceof VariantDefinition) {
866e5b51 318
1fbaecd1 319 /* Get the variant current field */
6bdc9fac 320 StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
866e5b51 321
21fb02fa
MK
322 /*
323 * Try to get the id field in the current field of the variant.
324 * If it is present, it overrides the previously read event id.
325 */
6bdc9fac
AM
326 Definition idIntegerDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
327 if (idIntegerDef instanceof IntegerDefinition) {
328 eventID = ((IntegerDefinition) idIntegerDef).getValue();
21fb02fa 329 }
866e5b51 330
6bdc9fac 331 /* Get the timestamp. This would overwrite any previous timestamp definition */
1fbaecd1 332 timestampDef = variantCurrentField.lookupDefinition("timestamp"); //$NON-NLS-1$
6bdc9fac
AM
333 if (timestampDef instanceof IntegerDefinition) {
334 timestamp = calculateTimestamp((IntegerDefinition) timestampDef);
335 }
21fb02fa 336 }
866e5b51
FC
337 }
338
1fbaecd1
AM
339 /* Read the stream event context. */
340 if (streamEventContextDef != null) {
341 streamEventContextDef.read(currentBitBuffer);
866e5b51
FC
342 }
343
1fbaecd1 344 /* Get the right event definition using the event id. */
866e5b51
FC
345 EventDefinition eventDef = events.get(eventID);
346 if (eventDef == null) {
347 throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
348 }
349
1fbaecd1 350 /* Read the event context. */
aa572e22
MK
351 if (eventDef.getContext() != null) {
352 eventDef.getContext().read(currentBitBuffer);
866e5b51
FC
353 }
354
1fbaecd1 355 /* Read the event fields. */
aa572e22
MK
356 if (eventDef.getFields() != null) {
357 eventDef.getFields().read(currentBitBuffer);
866e5b51
FC
358 }
359
360 /*
361 * Set the event timestamp using the timestamp calculated by
362 * updateTimestamp.
363 */
aa572e22 364 eventDef.setTimestamp(timestamp);
866e5b51
FC
365
366 return eventDef;
367 }
368
369 /**
370 * Calculates the timestamp value of the event, possibly using the timestamp
371 * from the last event.
372 *
373 * @param timestampDef
374 * Integer definition of the timestamp.
375 * @return The calculated timestamp value.
376 */
377 private long calculateTimestamp(IntegerDefinition timestampDef) {
378 long newval;
379 long majorasbitmask;
380 int len = timestampDef.getDeclaration().getLength();
381
382 /*
383 * If the timestamp length is 64 bits, it is a full timestamp.
384 */
385 if (timestampDef.getDeclaration().getLength() == 64) {
386 lastTimestamp = timestampDef.getValue();
387 return lastTimestamp;
388 }
389
390 /*
391 * Bit mask to keep / remove all old / new bits.
392 */
393 majorasbitmask = (1L << len) - 1;
394
395 /*
396 * If the new value is smaller than the corresponding bits of the last
397 * timestamp, we assume an overflow of the compact representation.
398 */
399 newval = timestampDef.getValue();
400 if (newval < (lastTimestamp & majorasbitmask)) {
401 newval = newval + (1L << len);
402 }
403
404 /* Keep only the high bits of the old value */
405 lastTimestamp = lastTimestamp & ~majorasbitmask;
406
407 /* Then add the low bits of the new value */
408 lastTimestamp = lastTimestamp + newval;
409
410 return lastTimestamp;
411 }
412
413 @Override
414 public Definition lookupDefinition(String lookupPath) {
415 // TODO Auto-generated method stub
416 return null;
417 }
866e5b51 418}
This page took 0.048918 seconds and 5 git commands to generate.