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