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