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