Fix bug when tracefile is not aligned. Now supports exotic architectures.
[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
FC
22import org.eclipse.linuxtools.ctf.core.event.types.Definition;
23import org.eclipse.linuxtools.ctf.core.event.types.EnumDefinition;
24import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
25import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
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/**
34 * <b><u>StreamInputPacketReader</u></b>
35 * <p>
36 * Reads the events of a packet of a trace file.
37 */
ce2388e0 38class StreamInputPacketReader implements IDefinitionScope {
866e5b51
FC
39
40 // ------------------------------------------------------------------------
41 // Constants
42 // ------------------------------------------------------------------------
43
44 /**
45 * Reference to the index entry of the current packet.
46 */
47 private StreamInputPacketIndexEntry currentPacket = null;
48
49 /**
50 * BitBuffer used to read the trace file.
51 */
52 private final BitBuffer bitBuffer = new BitBuffer();
53
54 /**
55 * StreamInputReader that uses this StreamInputPacketReader.
56 */
57 private final StreamInputReader streamInputReader;
58
59 /**
60 * Last timestamp recorded.
61 *
62 * Needed to calculate the complete timestamp values for the events with
63 * compact headers.
64 */
65 private long lastTimestamp = 0;
66
67 /**
68 * Trace packet header.
69 */
70 private StructDefinition tracePacketHeaderDef = null;
71
72 /**
73 * Stream packet context definition.
74 */
75 private StructDefinition streamPacketContextDef = null;
76
77 /**
78 * Stream event header definition.
79 */
80 private StructDefinition streamEventHeaderDef = null;
81
82 /**
83 * Stream event context definition.
84 */
85 private StructDefinition streamEventContextDef = null;
86
87 /**
88 * Maps event ID to event definitions.
89 */
90 private final HashMap<Long, EventDefinition> events = new HashMap<Long, EventDefinition>();
91
92 /**
93 * CPU id of current packet.
94 */
95 private int currentCpu = 0;
96
97 // ------------------------------------------------------------------------
98 // Attributes
99 // ------------------------------------------------------------------------
100
101 /**
102 * Constructs a StreamInputPacketReader.
103 *
104 * @param streamInputReader
105 * The StreamInputReader to which this packet reader belongs to.
106 */
107 public StreamInputPacketReader(StreamInputReader streamInputReader) {
108 this.streamInputReader = streamInputReader;
109
110 /*
111 * Set the BitBuffer's byte order.
112 */
ce2388e0 113 getBitBuffer().setByteOrder(streamInputReader.getByteOrder());
866e5b51
FC
114
115 /*
116 * Create definitions needed to read the events.
117 */
118 createDefinitions();
119 }
120
121 // ------------------------------------------------------------------------
122 // Constructors
123 // ------------------------------------------------------------------------
124
125 // ------------------------------------------------------------------------
126 // Getters/Setters/Predicates
127 // ------------------------------------------------------------------------
128
129 /* Getters, setters and stuff. */
130
131 public StreamInputPacketIndexEntry getCurrentPacket() {
132 return this.currentPacket;
133 }
134
135 public StructDefinition getStreamPacketContextDef() {
136 return this.streamPacketContextDef;
137 }
138
139 public int getCPU() {
140 return this.currentCpu;
141 }
142
143 @Override
144 public String getPath() {
145 return ""; //$NON-NLS-1$
146 }
147
148 // ------------------------------------------------------------------------
149 // Operations
150 // ------------------------------------------------------------------------
151
152 /**
153 * Creates definitions needed to read events (stream-defined and
154 * event-defined).
155 */
156 private void createDefinitions() {
157 /*
158 * Create trace packet header definition.
159 */
160 final Stream currentStream = getStreamInputReader().getStreamInput().getStream();
161 StructDeclaration tracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
162 if (tracePacketHeaderDecl != null) {
163 setTracePacketHeaderDef(tracePacketHeaderDecl.createDefinition(this,
164 "trace.packet.header")); //$NON-NLS-1$
165 }
166
167 /*
168 * Create stream packet context definition.
169 */
170 StructDeclaration streamPacketContextDecl = currentStream.getPacketContextDecl();
171 if (streamPacketContextDecl != null) {
172 setStreamPacketContextDef(streamPacketContextDecl.createDefinition(
173 this, "stream.packet.context")); //$NON-NLS-1$
174 }
175
176 /*
177 * Create stream event header definition.
178 */
179 StructDeclaration streamEventHeaderDecl = currentStream.getEventHeaderDecl();
180 if (streamEventHeaderDecl != null) {
181 setStreamEventHeaderDef(streamEventHeaderDecl.createDefinition(this,
182 "stream.event.header")); //$NON-NLS-1$
183 }
184
185 /*
186 * Create stream event context definition.
187 */
188 StructDeclaration streamEventContextDecl = currentStream.getEventContextDecl();
189 if (streamEventContextDecl != null) {
190 setStreamEventContextDef(streamEventContextDecl.createDefinition(
191 this, "stream.event.context")); //$NON-NLS-1$
192 }
193
194 createEventDefinitions();
195 }
196
197 /**
198 * Creates definitions needed to read the event. (event-defined).
199 */
200 private void createEventDefinitions() {
201 Collection<EventDeclaration> eventDecls = getStreamInputReader().getStreamInput().getStream().getEvents().values();
202
203 /*
204 * Create definitions for each event.
205 */
206 for (EventDeclaration event : eventDecls) {
207 EventDefinition eventDef = event.createDefinition(getStreamInputReader());
208
209 events.put(event.getId(), eventDef);
210 }
211 }
212
213 /**
214 * Changes the current packet to the given one.
215 *
216 * @param currentPacket
217 * The index entry of the packet to switch to.
218 */
219 public void setCurrentPacket(StreamInputPacketIndexEntry currentPacket) {
220 this.currentPacket = currentPacket;
221
222 if (this.currentPacket != null) {
223 /*
224 * Change the map of the BitBuffer.
225 */
226 MappedByteBuffer bb = null;
227 try {
228 bb = getStreamInputReader().getStreamInput().getFileChannel().map(
ce2388e0
FC
229 MapMode.READ_ONLY, this.currentPacket.getOffsetBytes(),
230 (this.currentPacket.getPacketSizeBits() + 7) / 8);
866e5b51
FC
231 } catch (IOException e) {
232 /*
233 * The streamInputReader object is already allocated, so this
234 * shouldn't fail bar some very bad kernel or RAM errors...
235 */
236 e.printStackTrace();
237 }
238
239 getBitBuffer().setByteBuffer(bb);
240
241 /*
242 * Read trace packet header.
243 */
244 if (getTracePacketHeaderDef() != null) {
245 getTracePacketHeaderDef().read(getBitBuffer());
246 }
247
248 /*
249 * Read stream packet context.
250 */
251 if (getStreamPacketContextDef() != null) {
252 getStreamPacketContextDef().read(getBitBuffer());
253 Definition cpuiddef = getStreamPacketContextDef().lookupDefinition("cpu_id"); //$NON-NLS-1$
254 if (cpuiddef instanceof IntegerDefinition) {
255 currentCpu = (int) ((IntegerDefinition) cpuiddef).getValue();
256 }
257 }
258
259 /*
260 * Use the timestamp begin of the packet as the reference for the
261 * timestamp reconstitution.
262 */
ce2388e0 263 lastTimestamp = currentPacket.getTimestampBegin();
866e5b51
FC
264 } else {
265 getBitBuffer().setByteBuffer(null);
266
267 lastTimestamp = 0;
268 }
269 }
270
271 /**
272 * Returns whether it is possible to read any more events from this packet.
273 *
274 * @return True if it is possible to read any more events from this packet.
275 */
276 public boolean hasMoreEvents() {
277 if (currentPacket != null) {
ce2388e0 278 return getBitBuffer().position() < currentPacket.getContentSizeBits();
866e5b51
FC
279 }
280 return false;
281 }
282
283 /**
284 * Reads the next event of the packet into the right event definition.
285 *
286 * @return The event definition containing the event data that was just
287 * read.
288 * @throws CTFReaderException
289 */
290 public EventDefinition readNextEvent() throws CTFReaderException {
291 /* WARNING: This is very LTTng-specific. */
292
293 Long eventID = null;
294 long timestamp = 0;
295
296 /*
fd74e6c1 297 * Read the stream event header.
866e5b51
FC
298 */
299 if (getStreamEventHeaderDef() != null) {
300 getStreamEventHeaderDef().read(getBitBuffer());
301
302 /*
303 * Check for an event id.
304 */
305 EnumDefinition idEnumDef = (EnumDefinition) getStreamEventHeaderDef().lookupDefinition("id"); //$NON-NLS-1$
306 assert (idEnumDef != null);
307
308 eventID = idEnumDef.getIntegerValue();
309
310 /*
311 * Check for the variant v.
312 */
313 VariantDefinition variantDef = (VariantDefinition) getStreamEventHeaderDef().lookupDefinition("v"); //$NON-NLS-1$
314 assert (variantDef != null);
315
316 /*
317 * Get the variant current field
318 */
319 StructDefinition variantCurrentField = (StructDefinition) variantDef.getCurrentField();
320 assert (variantCurrentField != null);
321
322 /*
323 * Try to get the id field in the current field of the variant. If
324 * it is present, it overrides the previously read event id.
325 */
326 IntegerDefinition idIntegerDef = (IntegerDefinition) variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
327 if (idIntegerDef != null) {
328 eventID = idIntegerDef.getValue();
329
330 }
331
332 /*
333 * Get the timestamp.
334 */
335 IntegerDefinition timestampDef = (IntegerDefinition) variantCurrentField.lookupDefinition("timestamp"); //$NON-NLS-1$
336 assert (timestampDef != null);
337
338 /*
339 * Calculate the event timestamp.
340 */
341 timestamp = calculateTimestamp(timestampDef);
342 }
343
344 /*
345 * Read the stream event context.
346 */
347 if (getStreamEventContextDef() != null) {
348 getStreamEventContextDef().read(getBitBuffer());
349 }
350
351 /*
352 * Get the right event definition using the event id.
353 */
354 EventDefinition eventDef = events.get(eventID);
355 if (eventDef == null) {
356 throw new CTFReaderException("Incorrect event id : " + eventID); //$NON-NLS-1$
357 }
358
359 /*
360 * Read the event context.
361 */
362 if (eventDef.context != null) {
363 eventDef.context.read(getBitBuffer());
364 }
365
366 /*
367 * Read the event fields.
368 */
369 if (eventDef.fields != null) {
fd74e6c1
MK
370 int pos = getBitBuffer().position();
371 int minAlign = (int) eventDef.fields.getDeclaration().getMinAlign();
372 int offset = pos % minAlign;
373 pos += (minAlign - offset)%minAlign;
374 getBitBuffer().position(pos);
866e5b51
FC
375 eventDef.fields.read(getBitBuffer());
376 }
377
378 /*
379 * Set the event timestamp using the timestamp calculated by
380 * updateTimestamp.
381 */
382 eventDef.timestamp = timestamp;
383
384 return eventDef;
385 }
386
387 /**
388 * Calculates the timestamp value of the event, possibly using the timestamp
389 * from the last event.
390 *
391 * @param timestampDef
392 * Integer definition of the timestamp.
393 * @return The calculated timestamp value.
394 */
395 private long calculateTimestamp(IntegerDefinition timestampDef) {
396 long newval;
397 long majorasbitmask;
398 int len = timestampDef.getDeclaration().getLength();
399
400 /*
401 * If the timestamp length is 64 bits, it is a full timestamp.
402 */
403 if (timestampDef.getDeclaration().getLength() == 64) {
404 lastTimestamp = timestampDef.getValue();
405 return lastTimestamp;
406 }
407
408 /*
409 * Bit mask to keep / remove all old / new bits.
410 */
411 majorasbitmask = (1L << len) - 1;
412
413 /*
414 * If the new value is smaller than the corresponding bits of the last
415 * timestamp, we assume an overflow of the compact representation.
416 */
417 newval = timestampDef.getValue();
418 if (newval < (lastTimestamp & majorasbitmask)) {
419 newval = newval + (1L << len);
420 }
421
422 /* Keep only the high bits of the old value */
423 lastTimestamp = lastTimestamp & ~majorasbitmask;
424
425 /* Then add the low bits of the new value */
426 lastTimestamp = lastTimestamp + newval;
427
428 return lastTimestamp;
429 }
430
431 @Override
432 public Definition lookupDefinition(String lookupPath) {
433 // TODO Auto-generated method stub
434 return null;
435 }
436
437 public StructDefinition getStreamEventContextDef() {
438 return this.streamEventContextDef;
439 }
440
441 public void setStreamEventContextDef(StructDefinition streamEventContextDef) {
442 this.streamEventContextDef = streamEventContextDef;
443 }
444
445 public StructDefinition getStreamEventHeaderDef() {
446 return this.streamEventHeaderDef;
447 }
448
449 public void setStreamEventHeaderDef(StructDefinition streamEventHeaderDef) {
450 this.streamEventHeaderDef = streamEventHeaderDef;
451 }
452
453 public void setStreamPacketContextDef(StructDefinition streamPacketContextDef) {
454 this.streamPacketContextDef = streamPacketContextDef;
455 }
456
457 public StructDefinition getTracePacketHeaderDef() {
458 return this.tracePacketHeaderDef;
459 }
460
461 public void setTracePacketHeaderDef(StructDefinition tracePacketHeaderDef) {
462 this.tracePacketHeaderDef = tracePacketHeaderDef;
463 }
464
465 public StreamInputReader getStreamInputReader() {
466 return this.streamInputReader;
467 }
468
469 public BitBuffer getBitBuffer() {
470 return bitBuffer;
471 }
472}
This page took 0.04333 seconds and 5 git commands to generate.