ctf: Introduce LostEventDeclaration singleton
[deliverable/tracecompass.git] / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / ctf / core / trace / CTFStreamInputPacketReader.java
CommitLineData
866e5b51 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
866e5b51
FC
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 *******************************************************************************/
f357bcd4 12package org.eclipse.tracecompass.ctf.core.trace;
866e5b51
FC
13
14import java.io.IOException;
526c823c 15import java.nio.ByteBuffer;
b3151232 16import java.nio.channels.FileChannel.MapMode;
866e5b51 17
a4fa4e36 18import org.eclipse.jdt.annotation.NonNull;
733c614c 19import org.eclipse.jdt.annotation.Nullable;
680f9173 20import org.eclipse.tracecompass.ctf.core.CTFException;
f357bcd4
AM
21import org.eclipse.tracecompass.ctf.core.CTFStrings;
22import org.eclipse.tracecompass.ctf.core.event.EventDefinition;
23import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
a433ce7d 24import org.eclipse.tracecompass.ctf.core.event.LostEventDeclaration;
f357bcd4
AM
25import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
26import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope;
fbe6fa6f 27import org.eclipse.tracecompass.ctf.core.event.scope.ILexicalScope;
f357bcd4
AM
28import org.eclipse.tracecompass.ctf.core.event.scope.LexicalScope;
29import org.eclipse.tracecompass.ctf.core.event.types.Definition;
30import org.eclipse.tracecompass.ctf.core.event.types.ICompositeDefinition;
31import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
32import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
33import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
34import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
35import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
36import org.eclipse.tracecompass.ctf.core.event.types.SimpleDatatypeDefinition;
37import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
38import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
39import org.eclipse.tracecompass.ctf.core.event.types.VariantDefinition;
40import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer;
f357bcd4 41import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition;
866e5b51
FC
42
43/**
d37aaa7f 44 * CTF trace packet reader. Reads the events of a packet of a trace file.
5c7202b5 45 *
d37aaa7f
FC
46 * @author Matthew Khouzam
47 * @author Simon Marchi
866e5b51 48 */
d84419e1 49public class CTFStreamInputPacketReader implements IDefinitionScope, AutoCloseable {
866e5b51
FC
50
51 // ------------------------------------------------------------------------
6bdc9fac 52 // Attributes
866e5b51
FC
53 // ------------------------------------------------------------------------
54
f068c622
MK
55 private static final int BITS_PER_BYTE = Byte.SIZE;
56
6bdc9fac 57 /** BitBuffer used to read the trace file. */
733c614c
MK
58 @Nullable
59 private BitBuffer fBitBuffer;
866e5b51 60
6bdc9fac 61 /** StreamInputReader that uses this StreamInputPacketReader. */
d84419e1 62 private final CTFStreamInputReader fStreamInputReader;
866e5b51 63
6bdc9fac 64 /** Trace packet header. */
a4fa4e36 65 private final StructDeclaration fTracePacketHeaderDecl;
866e5b51 66
6bdc9fac 67 /** Stream packet context definition. */
a4fa4e36 68 private final StructDeclaration fStreamPacketContextDecl;
866e5b51 69
6bdc9fac 70 /** Stream event header definition. */
6c7592e1 71 private final IDeclaration fStreamEventHeaderDecl;
866e5b51 72
c26d0fe0 73 /** Stream event context definition. */
a4fa4e36 74 private final StructDeclaration fStreamEventContextDecl;
866e5b51 75
6c7592e1
MK
76 private ICompositeDefinition fCurrentTracePacketHeaderDef;
77 private ICompositeDefinition fCurrentStreamEventHeaderDef;
78 private ICompositeDefinition fCurrentStreamPacketContextDef;
6bdc9fac 79 /** Reference to the index entry of the current packet. */
1d92f045 80 private ICTFPacketDescriptor fCurrentPacket = null;
6bdc9fac 81
866e5b51 82 /**
6bdc9fac
AM
83 * Last timestamp recorded.
84 *
85 * Needed to calculate the complete timestamp values for the events with
86 * compact headers.
866e5b51 87 */
2882273c 88 private long fLastTimestamp = 0;
6bdc9fac
AM
89
90 /** CPU id of current packet. */
2882273c 91 private int fCurrentCpu = 0;
866e5b51 92
2882273c 93 private int fLostEventsInThisPacket;
5c7202b5 94
2882273c 95 private long fLostEventsDuration;
c26d0fe0 96
2882273c 97 private boolean fHasLost = false;
c26d0fe0 98
866e5b51 99 // ------------------------------------------------------------------------
6bdc9fac 100 // Constructors
866e5b51
FC
101 // ------------------------------------------------------------------------
102
103 /**
104 * Constructs a StreamInputPacketReader.
105 *
106 * @param streamInputReader
107 * The StreamInputReader to which this packet reader belongs to.
108 */
d84419e1 109 public CTFStreamInputPacketReader(CTFStreamInputReader streamInputReader) {
2882273c 110 fStreamInputReader = streamInputReader;
866e5b51 111
6bdc9fac 112 /* Set the BitBuffer's byte order. */
6c7592e1
MK
113 ByteBuffer allocateDirect = ByteBuffer.allocateDirect(0);
114 if (allocateDirect == null) {
115 throw new IllegalStateException("Unable to allocate 0 bytes!"); //$NON-NLS-1$
116 }
117 fBitBuffer = new BitBuffer(allocateDirect);
33656d8e 118
d84419e1 119 final CTFStream currentStream = streamInputReader.getStreamInput().getStream();
a4fa4e36
MK
120 fTracePacketHeaderDecl = currentStream.getTrace().getPacketHeader();
121 fStreamPacketContextDecl = currentStream.getPacketContextDecl();
6c7592e1 122 fStreamEventHeaderDecl = currentStream.getEventHeaderDeclaration();
a4fa4e36
MK
123 fStreamEventContextDecl = currentStream.getEventContextDecl();
124 }
6bdc9fac 125
a4fa4e36
MK
126 /**
127 * Get the event context defintiion
128 *
129 * @param input
130 * the bitbuffer to read from
131 * @return an context definition, can be null
680f9173 132 * @throws CTFException
a4fa4e36 133 * out of bounds exception or such
a4fa4e36 134 */
680f9173 135 public StructDefinition getEventContextDefinition(@NonNull BitBuffer input) throws CTFException {
fbe6fa6f 136 return fStreamEventContextDecl.createDefinition(fStreamInputReader.getStreamInput(), ILexicalScope.STREAM_EVENT_CONTEXT, input);
a4fa4e36 137 }
6bdc9fac 138
a4fa4e36
MK
139 /**
140 * Get the packet context defintiion
141 *
142 * @param input
143 * the bitbuffer to read from
144 * @return an context definition, can be null
680f9173 145 * @throws CTFException
a4fa4e36 146 * out of bounds exception or such
a4fa4e36 147 */
680f9173 148 public StructDefinition getStreamPacketContextDefinition(@NonNull BitBuffer input) throws CTFException {
fbe6fa6f 149 return fStreamPacketContextDecl.createDefinition(fStreamInputReader.getStreamInput(), ILexicalScope.STREAM_PACKET_CONTEXT, input);
a4fa4e36 150 }
6bdc9fac 151
a4fa4e36
MK
152 /**
153 * Get the event header defintiion
154 *
155 * @param input
156 * the bitbuffer to read from
157 * @return an header definition, can be null
680f9173 158 * @throws CTFException
a4fa4e36 159 * out of bounds exception or such
a4fa4e36 160 */
680f9173 161 public StructDefinition getTracePacketHeaderDefinition(@NonNull BitBuffer input) throws CTFException {
fbe6fa6f 162 return fTracePacketHeaderDecl.createDefinition(fStreamInputReader.getStreamInput().getStream().getTrace(), ILexicalScope.TRACE_PACKET_HEADER, input);
6bdc9fac 163 }
866e5b51 164
5d1c6919
PT
165 /**
166 * Dispose the StreamInputPacketReader
5d1c6919 167 */
dd9752d5
AM
168 @Override
169 public void close() {
733c614c 170 fBitBuffer = null;
5d1c6919
PT
171 }
172
866e5b51
FC
173 // ------------------------------------------------------------------------
174 // Getters/Setters/Predicates
175 // ------------------------------------------------------------------------
176
9ac2eb62
MK
177 /**
178 * Gets the current packet
179 *
180 * @return the current packet
181 */
1d92f045 182 ICTFPacketDescriptor getCurrentPacket() {
2882273c 183 return fCurrentPacket;
866e5b51
FC
184 }
185
9ac2eb62
MK
186 /**
187 * Gets the CPU (core) number
188 *
189 * @return the CPU (core) number
190 */
866e5b51 191 public int getCPU() {
2882273c 192 return fCurrentCpu;
866e5b51
FC
193 }
194
195 @Override
a4fa4e36 196 public LexicalScope getScopePath() {
fbe6fa6f 197 return ILexicalScope.PACKET;
866e5b51
FC
198 }
199
200 // ------------------------------------------------------------------------
201 // Operations
202 // ------------------------------------------------------------------------
203
b3151232 204 @NonNull
680f9173 205 private ByteBuffer getByteBufferAt(long position, long size) throws CTFException, IOException {
f4a474e3 206 ByteBuffer map = SafeMappedByteBuffer.map(fStreamInputReader.getFc(), MapMode.READ_ONLY, position, size);
b3151232 207 if (map == null) {
680f9173 208 throw new CTFIOException("Failed to allocate mapped byte buffer"); //$NON-NLS-1$
b3151232
MK
209 }
210 return map;
211 }
f068c622 212
866e5b51
FC
213 /**
214 * Changes the current packet to the given one.
215 *
216 * @param currentPacket
217 * The index entry of the packet to switch to.
680f9173 218 * @throws CTFException
db8e8f7d 219 * If we get an error reading the packet
1d92f045 220 * @since 1.0
866e5b51 221 */
1d92f045
MK
222 public void setCurrentPacket(ICTFPacketDescriptor currentPacket) throws CTFException {
223 ICTFPacketDescriptor prevPacket = null;
2882273c 224 fCurrentPacket = currentPacket;
866e5b51 225
2882273c 226 if (fCurrentPacket != null) {
866e5b51
FC
227 /*
228 * Change the map of the BitBuffer.
229 */
526c823c 230 ByteBuffer bb = null;
866e5b51 231 try {
04f0148f 232 bb = getByteBufferAt(fCurrentPacket.getOffsetBytes(), (fCurrentPacket.getPacketSizeBits() + BITS_PER_BYTE - 1) / BITS_PER_BYTE);
866e5b51 233 } catch (IOException e) {
680f9173 234 throw new CTFIOException(e.getMessage(), e);
866e5b51
FC
235 }
236
733c614c
MK
237 BitBuffer bitBuffer = new BitBuffer(bb);
238 fBitBuffer = bitBuffer;
866e5b51
FC
239 /*
240 * Read trace packet header.
241 */
a4fa4e36 242 if (fTracePacketHeaderDecl != null) {
733c614c 243 fCurrentTracePacketHeaderDef = getTracePacketHeaderDefinition(bitBuffer);
866e5b51
FC
244 }
245
246 /*
247 * Read stream packet context.
248 */
a4fa4e36 249 if (fStreamPacketContextDecl != null) {
733c614c 250 fCurrentStreamPacketContextDef = getStreamPacketContextDefinition(bitBuffer);
33656d8e 251
132a02b0 252 /* Read CPU ID */
2882273c
MK
253 if (getCurrentPacket().getTarget() != null) {
254 fCurrentCpu = (int) getCurrentPacket().getTargetId();
866e5b51 255 }
21fb02fa 256
132a02b0 257 /* Read number of lost events */
2882273c
MK
258 fLostEventsInThisPacket = (int) getCurrentPacket().getLostEvents();
259 if (fLostEventsInThisPacket != 0) {
260 fHasLost = true;
c26d0fe0
AM
261 /*
262 * Compute the duration of the lost event time range. If the
263 * current packet is the first packet, duration will be set
264 * to 1.
265 */
266 long lostEventsStartTime;
3f02ac64 267 int index = fStreamInputReader.getStreamInput().getIndex().indexOf(currentPacket);
c26d0fe0
AM
268 if (index == 0) {
269 lostEventsStartTime = currentPacket.getTimestampBegin() + 1;
270 } else {
3f02ac64 271 prevPacket = fStreamInputReader.getStreamInput().getIndex().getElement(index - 1);
c26d0fe0
AM
272 lostEventsStartTime = prevPacket.getTimestampEnd();
273 }
2882273c 274 fLostEventsDuration = Math.abs(lostEventsStartTime - currentPacket.getTimestampBegin());
c26d0fe0 275 }
866e5b51
FC
276 }
277
278 /*
279 * Use the timestamp begin of the packet as the reference for the
280 * timestamp reconstitution.
281 */
2882273c 282 fLastTimestamp = currentPacket.getTimestampBegin();
866e5b51 283 } else {
733c614c 284 fBitBuffer = null;
2882273c 285 fLastTimestamp = 0;
866e5b51
FC
286 }
287 }
288
289 /**
290 * Returns whether it is possible to read any more events from this packet.
291 *
292 * @return True if it is possible to read any more events from this packet.
293 */
294 public boolean hasMoreEvents() {
733c614c 295 BitBuffer bitBuffer = fBitBuffer;
1d92f045 296 ICTFPacketDescriptor currentPacket = fCurrentPacket;
733c614c
MK
297 if (currentPacket != null && bitBuffer != null) {
298 return fHasLost || (bitBuffer.position() < currentPacket.getContentSizeBits());
866e5b51
FC
299 }
300 return false;
301 }
302
303 /**
304 * Reads the next event of the packet into the right event definition.
305 *
306 * @return The event definition containing the event data that was just
307 * read.
680f9173 308 * @throws CTFException
be6df2d8 309 * If there was a problem reading the trace
866e5b51 310 */
680f9173 311 public EventDefinition readNextEvent() throws CTFException {
1fbaecd1 312 /* Default values for those fields */
5f715709 313 // compromise since we cannot have 64 bit addressing of arrays yet.
a433ce7d 314 int eventID = (int) IEventDeclaration.UNSET_EVENT_ID;
866e5b51 315 long timestamp = 0;
2882273c
MK
316 if (fHasLost) {
317 fHasLost = false;
a433ce7d 318 IEventDeclaration lostEventDeclaration = LostEventDeclaration.INSTANCE;
a4fa4e36
MK
319 StructDeclaration lostFields = lostEventDeclaration.getFields();
320 // this is a hard coded map, we know it's not null
2db699c2 321 IntegerDeclaration lostFieldsDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_FIELD);
a4fa4e36
MK
322 if (lostFieldsDecl == null)
323 {
324 throw new IllegalStateException("Lost events count not declared!"); //$NON-NLS-1$
325 }
2db699c2 326 IntegerDeclaration lostEventsDurationDecl = (IntegerDeclaration) lostFields.getField(CTFStrings.LOST_EVENTS_DURATION);
a4fa4e36
MK
327 if (lostEventsDurationDecl == null) {
328 throw new IllegalStateException("Lost events duration not declared!"); //$NON-NLS-1$
329 }
330 IntegerDefinition lostDurationDef = new IntegerDefinition(lostFieldsDecl, null, CTFStrings.LOST_EVENTS_DURATION, fLostEventsDuration);
331 IntegerDefinition lostCountDef = new IntegerDefinition(lostEventsDurationDecl, null, CTFStrings.LOST_EVENTS_FIELD, fLostEventsInThisPacket);
332 IntegerDefinition[] fields = new IntegerDefinition[] { lostCountDef, lostDurationDef };
a4fa4e36
MK
333 return new EventDefinition(
334 lostEventDeclaration,
335 fStreamInputReader,
336 fLastTimestamp,
337 null,
338 null,
339 null,
340 new StructDefinition(
341 lostFields,
342 this, "fields", //$NON-NLS-1$
a4fa4e36
MK
343 fields
344 ));
345
33656d8e 346 }
132a02b0 347
2882273c 348 final BitBuffer currentBitBuffer = fBitBuffer;
6c7592e1 349 if (currentBitBuffer == null) {
733c614c
MK
350 return null;
351 }
cf9a28da 352 final long posStart = currentBitBuffer.position();
1fbaecd1 353 /* Read the stream event header. */
a4fa4e36 354 if (fStreamEventHeaderDecl != null) {
6c7592e1
MK
355 if (fStreamEventHeaderDecl instanceof IEventHeaderDeclaration) {
356 fCurrentStreamEventHeaderDef = (ICompositeDefinition) fStreamEventHeaderDecl.createDefinition(null, "", currentBitBuffer); //$NON-NLS-1$
357 EventHeaderDefinition ehd = (EventHeaderDefinition) fCurrentStreamEventHeaderDef;
358 eventID = ehd.getId();
359 timestamp = calculateTimestamp(ehd.getTimestamp(), ehd.getTimestampLength());
360 } else {
fbe6fa6f 361 fCurrentStreamEventHeaderDef = ((StructDeclaration) fStreamEventHeaderDecl).createDefinition(null, ILexicalScope.EVENT_HEADER, currentBitBuffer);
6c7592e1
MK
362 StructDefinition StructEventHeaderDef = (StructDefinition) fCurrentStreamEventHeaderDef;
363 /* Check for the event id. */
364 IDefinition idDef = StructEventHeaderDef.lookupDefinition("id"); //$NON-NLS-1$
365 SimpleDatatypeDefinition simpleIdDef = null;
366 if (idDef instanceof SimpleDatatypeDefinition) {
367 simpleIdDef = ((SimpleDatatypeDefinition) idDef);
368 } else if (idDef != null) {
680f9173 369 throw new CTFIOException("Id defintion not an integer, enum or float definiton in event header."); //$NON-NLS-1$
6c7592e1 370 }
866e5b51 371
6c7592e1
MK
372 /*
373 * Get the timestamp from the event header (may be overridden
374 * later on)
375 */
376 IntegerDefinition timestampDef = StructEventHeaderDef.lookupInteger("timestamp"); //$NON-NLS-1$
1fbaecd1 377
6c7592e1
MK
378 /* Check for the variant v. */
379 IDefinition variantDef = StructEventHeaderDef.lookupDefinition("v"); //$NON-NLS-1$
380 if (variantDef instanceof VariantDefinition) {
866e5b51 381
6c7592e1
MK
382 /* Get the variant current field */
383 StructDefinition variantCurrentField = (StructDefinition) ((VariantDefinition) variantDef).getCurrentField();
866e5b51 384
6c7592e1
MK
385 /*
386 * Try to get the id field in the current field of the
387 * variant. If it is present, it overrides the previously
388 * read event id.
389 */
390 IDefinition vIdDef = variantCurrentField.lookupDefinition("id"); //$NON-NLS-1$
391 if (vIdDef instanceof IntegerDefinition) {
392 simpleIdDef = (SimpleDatatypeDefinition) vIdDef;
393 }
866e5b51 394
6c7592e1
MK
395 /*
396 * Get the timestamp. This would overwrite any previous
397 * timestamp definition
398 */
399 timestampDef = variantCurrentField.lookupInteger("timestamp"); //$NON-NLS-1$
6bdc9fac 400 }
6c7592e1 401 if (simpleIdDef != null) {
5f715709 402 eventID = simpleIdDef.getIntegerValue().intValue();
6c7592e1
MK
403 }
404 if (timestampDef != null) {
405 timestamp = calculateTimestamp(timestampDef);
406 } // else timestamp remains 0
21fb02fa 407 }
866e5b51 408 }
1fbaecd1 409 /* Get the right event definition using the event id. */
5f715709 410 IEventDeclaration eventDeclaration = fStreamInputReader.getStreamInput().getStream().getEventDeclaration(eventID);
a4fa4e36 411 if (eventDeclaration == null) {
680f9173 412 throw new CTFIOException("Incorrect event id : " + eventID); //$NON-NLS-1$
866e5b51 413 }
733c614c 414 EventDefinition eventDef = eventDeclaration.createDefinition(fStreamInputReader, currentBitBuffer, timestamp);
866e5b51
FC
415
416 /*
417 * Set the event timestamp using the timestamp calculated by
418 * updateTimestamp.
419 */
866e5b51 420
cf9a28da 421 if (posStart == currentBitBuffer.position()) {
680f9173 422 throw new CTFIOException("Empty event not allowed, event: " + eventDef.getDeclaration().getName()); //$NON-NLS-1$
cf9a28da
MK
423 }
424
866e5b51
FC
425 return eventDef;
426 }
427
428 /**
429 * Calculates the timestamp value of the event, possibly using the timestamp
430 * from the last event.
431 *
432 * @param timestampDef
433 * Integer definition of the timestamp.
434 * @return The calculated timestamp value.
435 */
436 private long calculateTimestamp(IntegerDefinition timestampDef) {
866e5b51 437 int len = timestampDef.getDeclaration().getLength();
6c7592e1 438 final long value = timestampDef.getValue();
866e5b51 439
6c7592e1
MK
440 return calculateTimestamp(value, len);
441 }
442
443 private long calculateTimestamp(final long value, int len) {
444 long newval;
445 long majorasbitmask;
866e5b51
FC
446 /*
447 * If the timestamp length is 64 bits, it is a full timestamp.
448 */
f068c622 449 if (len == Long.SIZE) {
6c7592e1 450 fLastTimestamp = value;
2882273c 451 return fLastTimestamp;
866e5b51
FC
452 }
453
454 /*
455 * Bit mask to keep / remove all old / new bits.
456 */
457 majorasbitmask = (1L << len) - 1;
458
459 /*
460 * If the new value is smaller than the corresponding bits of the last
461 * timestamp, we assume an overflow of the compact representation.
462 */
6c7592e1 463 newval = value;
2882273c 464 if (newval < (fLastTimestamp & majorasbitmask)) {
866e5b51
FC
465 newval = newval + (1L << len);
466 }
467
468 /* Keep only the high bits of the old value */
2882273c 469 fLastTimestamp = fLastTimestamp & ~majorasbitmask;
866e5b51
FC
470
471 /* Then add the low bits of the new value */
2882273c 472 fLastTimestamp = fLastTimestamp + newval;
866e5b51 473
2882273c 474 return fLastTimestamp;
866e5b51
FC
475 }
476
477 @Override
478 public Definition lookupDefinition(String lookupPath) {
fbe6fa6f 479 if (lookupPath.equals(ILexicalScope.STREAM_PACKET_CONTEXT.getPath())) {
6c7592e1 480 return (Definition) fCurrentStreamPacketContextDef;
a4fa4e36 481 }
fbe6fa6f 482 if (lookupPath.equals(ILexicalScope.TRACE_PACKET_HEADER.getPath())) {
6c7592e1 483 return (Definition) fCurrentTracePacketHeaderDef;
a4fa4e36 484 }
866e5b51
FC
485 return null;
486 }
a4fa4e36 487
6c7592e1
MK
488
489 /**
490 * Get stream event header
491 *
492 * @return the stream event header
6c7592e1
MK
493 */
494 public ICompositeDefinition getStreamEventHeaderDefinition() {
a4fa4e36
MK
495 return fCurrentStreamEventHeaderDef;
496 }
497
498 /**
499 * Get the current packet event header
500 *
501 * @return the current packet event header
a4fa4e36
MK
502 */
503 public StructDefinition getCurrentPacketEventHeader() {
6c7592e1
MK
504 if (fCurrentTracePacketHeaderDef instanceof StructDefinition) {
505 return (StructDefinition) fCurrentTracePacketHeaderDef;
506 }
507 return null;
a4fa4e36 508 }
866e5b51 509}
This page took 0.089389 seconds and 5 git commands to generate.