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