tmf: Correctly export all packages in runtime plugins
[deliverable/tracecompass.git] / org.eclipse.linuxtools.ctf.core / src / org / eclipse / linuxtools / internal / ctf / core / trace / StreamInput.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 *******************************************************************************/
12
ce2388e0 13package org.eclipse.linuxtools.internal.ctf.core.trace;
866e5b51
FC
14
15import java.io.File;
aa3b05ef
FC
16import java.io.IOException;
17import java.nio.MappedByteBuffer;
866e5b51 18import java.nio.channels.FileChannel;
aa3b05ef 19import java.nio.channels.FileChannel.MapMode;
866e5b51
FC
20import java.util.UUID;
21
866e5b51
FC
22import org.eclipse.linuxtools.ctf.core.event.types.ArrayDefinition;
23import org.eclipse.linuxtools.ctf.core.event.types.Definition;
21fb02fa
MK
24import org.eclipse.linuxtools.ctf.core.event.types.EnumDefinition;
25import org.eclipse.linuxtools.ctf.core.event.types.FloatDefinition;
866e5b51
FC
26import org.eclipse.linuxtools.ctf.core.event.types.IDefinitionScope;
27import org.eclipse.linuxtools.ctf.core.event.types.IntegerDefinition;
21fb02fa 28import org.eclipse.linuxtools.ctf.core.event.types.StringDefinition;
866e5b51 29import org.eclipse.linuxtools.ctf.core.event.types.StructDefinition;
ce2388e0
FC
30import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
31import org.eclipse.linuxtools.ctf.core.trace.Utils;
32import org.eclipse.linuxtools.internal.ctf.core.event.io.BitBuffer;
866e5b51
FC
33
34/**
35 * <b><u>StreamInput</u></b>
36 * <p>
37 * Represents a trace file that belongs to a certain stream.
38 */
39public class StreamInput implements IDefinitionScope {
40
41 // ------------------------------------------------------------------------
42 // Attributes
43 // ------------------------------------------------------------------------
44
45 /**
46 * The associated Stream
47 */
48 private final Stream stream;
49
50 /**
51 * FileChannel to the trace file
52 */
53 private final FileChannel fileChannel;
54
55 /**
56 * Information on the file (used for debugging)
57 */
58 public final File file;
59
60 /**
61 * The packet index of this input
62 */
bfe038ff 63 private final StreamInputPacketIndex index;
866e5b51
FC
64
65 private long timestampEnd;
66
bfe038ff
MK
67 /*
68 * Definition of trace packet header
69 */
70 StructDefinition tracePacketHeaderDef = null;
71
72 /*
73 * Definition of trace stream packet context
74 */
75 StructDefinition streamPacketContextDef = null;
76
132a02b0
MK
77 /*
78 * Total number of lost events in this stream
79 */
80 long lostSoFar = 0;
81
866e5b51
FC
82 // ------------------------------------------------------------------------
83 // Constructors
84 // ------------------------------------------------------------------------
85
86 /**
87 * Constructs a StreamInput.
88 *
89 * @param stream
90 * The stream to which this StreamInput belongs to.
91 * @param fileChannel
92 * The FileChannel to the trace file.
93 * @param file
94 * Information about the trace file (for debugging purposes).
95 */
96 public StreamInput(Stream stream, FileChannel fileChannel, File file) {
97 this.stream = stream;
98 this.fileChannel = fileChannel;
99 this.file = file;
1fbaecd1 100 this.index = stream.getTrace().getIndex(this);
866e5b51
FC
101 }
102
103 // ------------------------------------------------------------------------
104 // Getters/Setters/Predicates
105 // ------------------------------------------------------------------------
106
9ac2eb62
MK
107 /**
108 * Gets the stream the streamInput wrapper is wrapping
21fb02fa 109 *
9ac2eb62
MK
110 * @return the stream the streamInput wrapper is wrapping
111 */
866e5b51
FC
112 public Stream getStream() {
113 return stream;
114 }
115
9ac2eb62
MK
116 /**
117 * the common streamInput Index
21fb02fa 118 *
9ac2eb62
MK
119 * @return the stream input Index
120 */
866e5b51
FC
121 public StreamInputPacketIndex getIndex() {
122 return index;
123 }
124
9ac2eb62 125 /**
21fb02fa
MK
126 * Gets the filechannel of the streamInput. This is a limited Java
127 * ressource.
128 *
9ac2eb62
MK
129 * @return the filechannel
130 */
866e5b51
FC
131 public FileChannel getFileChannel() {
132 return fileChannel;
133 }
134
9ac2eb62
MK
135 /**
136 * Gets the filename of the streamInput file.
21fb02fa 137 *
9ac2eb62
MK
138 * @return the filename of the streaminput file.
139 */
866e5b51
FC
140 public String getFilename() {
141 return file.getName();
142 }
143
9ac2eb62 144 /**
21fb02fa
MK
145 * gets the last read timestamp of a stream. (this is not necessarily the
146 * last time in the stream.)
147 *
9ac2eb62
MK
148 * @return the last read timestamp
149 */
866e5b51
FC
150 public long getTimestampEnd() {
151 return timestampEnd;
152 }
153
9ac2eb62 154 /**
21fb02fa
MK
155 * Sets the last read timestamp of a stream. (this is not necessarily the
156 * last time in the stream.)
157 *
158 * @param timestampEnd
159 * the last read timestamp
9ac2eb62 160 */
866e5b51
FC
161 public void setTimestampEnd(long timestampEnd) {
162 this.timestampEnd = timestampEnd;
163 }
164
9ac2eb62
MK
165 /**
166 * useless for streaminputs
167 */
866e5b51
FC
168 @Override
169 public String getPath() {
170 return ""; //$NON-NLS-1$
171 }
172
173 // ------------------------------------------------------------------------
174 // Operations
175 // ------------------------------------------------------------------------
176
177 @Override
178 public Definition lookupDefinition(String lookupPath) {
179 /* TODO: lookup in different dynamic scopes is not supported yet. */
180 return null;
181 }
182
183 /**
184 * Create the index for this trace file.
bfe038ff
MK
185 */
186 public void setupIndex() {
187
bfe038ff
MK
188 /*
189 * The BitBuffer to extract data from the StreamInput
190 */
191 BitBuffer bitBuffer = new BitBuffer();
8b8e48ed 192 bitBuffer.setByteOrder(this.getStream().getTrace().getByteOrder());
bfe038ff
MK
193
194 /*
195 * Create the definitions we need to read the packet headers + contexts
196 */
197 if (getStream().getTrace().getPacketHeader() != null) {
198 tracePacketHeaderDef = getStream().getTrace().getPacketHeader()
199 .createDefinition(this, "trace.packet.header"); //$NON-NLS-1$
200 }
201
202 if (getStream().getPacketContextDecl() != null) {
203 streamPacketContextDef = getStream().getPacketContextDecl()
204 .createDefinition(this, "stream.packet.context"); //$NON-NLS-1$
205 }
206
207 }
208
9ac2eb62
MK
209 /**
210 * Adds the next packet header index entry to the index of a stream input.
be6df2d8
AM
211 *
212 * @warning slow, can corrupt data if not used properly
9ac2eb62
MK
213 * @return true if there are more packets to add
214 * @throws CTFReaderException
be6df2d8 215 * If there was a problem reading the packed header
9ac2eb62 216 */
bfe038ff
MK
217 public boolean addPacketHeaderIndex() throws CTFReaderException {
218 long currentPos = 0L;
219 if (!index.getEntries().isEmpty()) {
220 StreamInputPacketIndexEntry pos = index.getEntries().lastElement();
221 currentPos = computeNextOffset(pos);
222 }
223 long fileSize = getStreamSize();
224 if (currentPos < fileSize) {
225 BitBuffer bitBuffer = new BitBuffer();
8b8e48ed 226 bitBuffer.setByteOrder(this.getStream().getTrace().getByteOrder());
bfe038ff
MK
227 StreamInputPacketIndexEntry packetIndex = new StreamInputPacketIndexEntry(
228 currentPos);
229 createPacketIndexEntry(fileSize, currentPos, packetIndex,
230 tracePacketHeaderDef, streamPacketContextDef, bitBuffer);
231 index.addEntry(packetIndex);
232 return true;
233 }
234 return false;
235 }
236
bfe038ff
MK
237 private long getStreamSize() {
238 return file.length();
239 }
240
bfe038ff
MK
241 private long createPacketIndexEntry(long fileSizeBytes,
242 long packetOffsetBytes, StreamInputPacketIndexEntry packetIndex,
243 StructDefinition tracePacketHeaderDef,
244 StructDefinition streamPacketContextDef, BitBuffer bitBuffer)
245 throws CTFReaderException {
21fb02fa
MK
246 @SuppressWarnings("unused")
247 MappedByteBuffer bb = createPacketBitBuffer(fileSizeBytes,
aa3b05ef 248 packetOffsetBytes, packetIndex, bitBuffer);
bfe038ff 249
866e5b51 250 /*
bfe038ff 251 * Read the trace packet header if it exists.
866e5b51 252 */
bfe038ff
MK
253 if (tracePacketHeaderDef != null) {
254 parseTracePacketHeader(tracePacketHeaderDef, bitBuffer);
866e5b51
FC
255 }
256
257 /*
bfe038ff 258 * Read the stream packet context if it exists.
866e5b51 259 */
bfe038ff
MK
260 if (streamPacketContextDef != null) {
261 parsePacketContext(fileSizeBytes, streamPacketContextDef,
262 bitBuffer, packetIndex);
263 } else {
264 setPacketContextNull(fileSizeBytes, packetIndex);
265 }
266
267 /* Basic validation */
268 if (packetIndex.getContentSizeBits() > packetIndex.getPacketSizeBits()) {
269 throw new CTFReaderException("Content size > packet size"); //$NON-NLS-1$
270 }
866e5b51 271
bfe038ff
MK
272 if (packetIndex.getPacketSizeBits() > ((fileSizeBytes - packetIndex
273 .getOffsetBytes()) * 8)) {
274 throw new CTFReaderException(
275 "Not enough data remaining in the file for the size of this packet"); //$NON-NLS-1$
276 }
277
278 /*
279 * Offset in the file, in bits
280 */
281 packetIndex.setDataOffsetBits(bitBuffer.position());
282
283 /*
284 * Update the counting packet offset
285 */
21fb02fa 286 return computeNextOffset(packetIndex);
bfe038ff
MK
287 }
288
289 /**
290 * @param packetIndex
291 * @return
292 */
293 private static long computeNextOffset(
294 StreamInputPacketIndexEntry packetIndex) {
295 return packetIndex.getOffsetBytes()
296 + ((packetIndex.getPacketSizeBits() + 7) / 8);
297 }
298
aa3b05ef
FC
299 /**
300 * @param fileSizeBytes
301 * @param packetOffsetBytes
302 * @param packetIndex
303 * @param bitBuffer
304 * @return
305 * @throws CTFReaderException
306 */
307 private MappedByteBuffer createPacketBitBuffer(long fileSizeBytes,
308 long packetOffsetBytes, StreamInputPacketIndexEntry packetIndex,
309 BitBuffer bitBuffer) throws CTFReaderException {
310 /*
311 * Initial size, it should map at least the packet header + context
312 * size.
313 *
314 * TODO: use a less arbitrary size.
315 */
316 long mapSize = 4096;
317 /*
318 * If there is less data remaining than what we want to map, reduce the
319 * map size.
320 */
321 if ((fileSizeBytes - packetIndex.getOffsetBytes()) < mapSize) {
322 mapSize = fileSizeBytes - packetIndex.getOffsetBytes();
323 }
324
325 /*
326 * Map the packet.
327 */
328 MappedByteBuffer bb;
329
330 try {
331 bb = fileChannel.map(MapMode.READ_ONLY, packetOffsetBytes, mapSize);
332 } catch (IOException e) {
333 throw new CTFReaderException(e);
334 }
335 bitBuffer.setByteBuffer(bb);
336 return bb;
337 }
bfe038ff 338
bfe038ff
MK
339 private void parseTracePacketHeader(StructDefinition tracePacketHeaderDef,
340 BitBuffer bitBuffer) throws CTFReaderException {
341 tracePacketHeaderDef.read(bitBuffer);
866e5b51
FC
342
343 /*
bfe038ff 344 * Check the CTF magic number
866e5b51 345 */
bfe038ff
MK
346 IntegerDefinition magicDef = (IntegerDefinition) tracePacketHeaderDef
347 .lookupDefinition("magic"); //$NON-NLS-1$
348 if (magicDef != null) {
349 int magic = (int) magicDef.getValue();
350 if (magic != Utils.CTF_MAGIC) {
351 throw new CTFReaderException(
352 "CTF magic mismatch " + Integer.toHexString(magic) + " vs " + Integer.toHexString(Utils.CTF_MAGIC)); //$NON-NLS-1$//$NON-NLS-2$
353 }
866e5b51 354
866e5b51
FC
355 }
356
357 /*
bfe038ff 358 * Check the trace UUID
866e5b51 359 */
bfe038ff
MK
360 ArrayDefinition uuidDef = (ArrayDefinition) tracePacketHeaderDef
361 .lookupDefinition("uuid"); //$NON-NLS-1$
362 if (uuidDef != null) {
363 byte[] uuidArray = new byte[16];
364
365 for (int i = 0; i < 16; i++) {
366 IntegerDefinition uuidByteDef = (IntegerDefinition) uuidDef
367 .getElem(i);
368 uuidArray[i] = (byte) uuidByteDef.getValue();
866e5b51 369 }
866e5b51 370
bfe038ff 371 UUID uuid = Utils.makeUUID(uuidArray);
866e5b51 372
bfe038ff
MK
373 if (!getStream().getTrace().getUUID().equals(uuid)) {
374 throw new CTFReaderException("UUID mismatch"); //$NON-NLS-1$
866e5b51 375 }
bfe038ff 376 }
866e5b51 377
bfe038ff
MK
378 /*
379 * Check that the stream id did not change
380 */
381 IntegerDefinition streamIDDef = (IntegerDefinition) tracePacketHeaderDef
382 .lookupDefinition("stream_id"); //$NON-NLS-1$
383 if (streamIDDef != null) {
384 long streamID = streamIDDef.getValue();
866e5b51 385
bfe038ff 386 if (streamID != getStream().getId()) {
866e5b51 387 throw new CTFReaderException(
bfe038ff 388 "Stream ID changing within a StreamInput"); //$NON-NLS-1$
866e5b51 389 }
bfe038ff
MK
390 }
391 }
866e5b51 392
bfe038ff
MK
393 private static void setPacketContextNull(long fileSizeBytes,
394 StreamInputPacketIndexEntry packetIndex) {
395 /*
396 * If there is no packet context, infer the content and packet size from
397 * the file size (assume that there is only one packet and no padding)
398 */
399 packetIndex.setContentSizeBits((int) (fileSizeBytes * 8));
400 packetIndex.setPacketSizeBits((int) (fileSizeBytes * 8));
401 }
866e5b51 402
bfe038ff
MK
403 private void parsePacketContext(long fileSizeBytes,
404 StructDefinition streamPacketContextDef, BitBuffer bitBuffer,
405 StreamInputPacketIndexEntry packetIndex) {
406 streamPacketContextDef.read(bitBuffer);
866e5b51 407
21fb02fa
MK
408 for (String field : streamPacketContextDef.getDeclaration()
409 .getFieldsList()) {
410 Definition id = streamPacketContextDef.lookupDefinition(field);
411 if (id instanceof IntegerDefinition) {
412 packetIndex.addAttribute(field,
413 ((IntegerDefinition) id).getValue());
414 } else if (id instanceof FloatDefinition) {
415 packetIndex.addAttribute(field,
416 ((FloatDefinition) id).getValue());
417 } else if (id instanceof EnumDefinition) {
418 packetIndex.addAttribute(field,
419 ((EnumDefinition) id).getValue());
420 } else if (id instanceof StringDefinition) {
421 packetIndex.addAttribute(field,
422 ((StringDefinition) id).getValue());
423 }
21fb02fa
MK
424 }
425
426 Long contentSize = (Long) packetIndex.lookupAttribute("content_size"); //$NON-NLS-1$
427 Long packetSize = (Long) packetIndex.lookupAttribute("packet_size"); //$NON-NLS-1$
132a02b0 428 Long timestampBegin = (Long) packetIndex.lookupAttribute("timestamp_begin"); //$NON-NLS-1$
21fb02fa
MK
429 Long timestampEnd = (Long) packetIndex.lookupAttribute("timestamp_end"); //$NON-NLS-1$
430 String device = (String) packetIndex.lookupAttribute("device"); //$NON-NLS-1$
431 // LTTng Specific
432 Long CPU_ID = (Long) packetIndex.lookupAttribute("cpu_id"); //$NON-NLS-1$
132a02b0
MK
433 Long lostEvents = (Long) packetIndex.lookupAttribute("events_discarded"); //$NON-NLS-1$
434
435 /* Read the content size in bits */
21fb02fa
MK
436 if (contentSize != null) {
437 packetIndex.setContentSizeBits(contentSize.intValue());
bfe038ff
MK
438 } else {
439 packetIndex.setContentSizeBits((int) (fileSizeBytes * 8));
440 }
866e5b51 441
132a02b0 442 /* Read the packet size in bits */
21fb02fa
MK
443 if (packetSize != null) {
444 packetIndex.setPacketSizeBits(packetSize.intValue());
bfe038ff
MK
445 } else {
446 if (packetIndex.getContentSizeBits() != 0) {
447 packetIndex.setPacketSizeBits(packetIndex.getContentSizeBits());
448 } else {
449 packetIndex.setPacketSizeBits((int) (fileSizeBytes * 8));
450 }
451 }
452
132a02b0 453 /* Read the begin timestamp */
21fb02fa
MK
454 if (timestampBegin != null) {
455 packetIndex.setTimestampBegin(timestampBegin.longValue());
bfe038ff
MK
456 }
457
132a02b0 458 /* Read the end timestamp */
21fb02fa
MK
459 if (timestampEnd != null) {
460 if( timestampEnd == -1 ) {
461 timestampEnd = Long.MAX_VALUE;
462 }
463 packetIndex.setTimestampEnd(timestampEnd.longValue());
bfe038ff 464 setTimestampEnd(packetIndex.getTimestampEnd());
866e5b51 465 }
21fb02fa
MK
466
467 if (device != null) {
468 packetIndex.setTarget(device);
469 }
470
471 if (CPU_ID != null) {
472 packetIndex.setTarget("CPU" + CPU_ID.toString()); //$NON-NLS-1$
473 }
132a02b0
MK
474
475 if (lostEvents != null) {
476 packetIndex.setLostEvents(lostEvents - lostSoFar);
477 this.lostSoFar = lostEvents;
478 }
866e5b51
FC
479 }
480
bfe038ff
MK
481 /*
482 * (non-Javadoc)
483 *
81c8e6f7
MK
484 * @see java.lang.Object#hashCode()
485 */
486 @Override
487 public int hashCode() {
488 final int prime = 31;
489 int result = 1;
490 result = (prime * result) + ((file == null) ? 0 : file.hashCode());
491 return result;
492 }
493
bfe038ff
MK
494 /*
495 * (non-Javadoc)
496 *
81c8e6f7
MK
497 * @see java.lang.Object#equals(java.lang.Object)
498 */
499 @Override
500 public boolean equals(Object obj) {
501 if (this == obj) {
502 return true;
503 }
504 if (obj == null) {
505 return false;
506 }
507 if (!(obj instanceof StreamInput)) {
508 return false;
509 }
510 StreamInput other = (StreamInput) obj;
511 if (file == null) {
512 if (other.file != null) {
513 return false;
514 }
515 } else if (!file.equals(other.file)) {
516 return false;
517 }
518 return true;
519 }
520
866e5b51 521}
This page took 0.061491 seconds and 5 git commands to generate.