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