ctf: Introduce ICTFStream
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / ctf / core / trace / CTFTrace.java
CommitLineData
866e5b51 1/*******************************************************************************
fe75d403 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 *
4311ac8b
MAL
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
11 * Alexandre Montplaisir - Initial API and implementation
890f9136 12 * Simon Delisle - Replace LinkedList by TreeSet in callsitesByName attribute
866e5b51
FC
13 *******************************************************************************/
14
f357bcd4 15package org.eclipse.tracecompass.ctf.core.trace;
866e5b51
FC
16
17import java.io.File;
18import java.io.FileFilter;
866e5b51 19import java.io.IOException;
debcffff 20import java.io.Serializable;
f4a474e3 21import java.nio.ByteBuffer;
866e5b51 22import java.nio.ByteOrder;
866e5b51
FC
23import java.nio.channels.FileChannel;
24import java.nio.channels.FileChannel.MapMode;
219d054e 25import java.nio.file.StandardOpenOption;
866e5b51 26import java.util.Arrays;
5f715709 27import java.util.Collection;
a95fddf5 28import java.util.Collections;
866e5b51
FC
29import java.util.Comparator;
30import java.util.HashMap;
31import java.util.Map;
32import java.util.Set;
33import java.util.UUID;
34
680f9173 35import org.eclipse.tracecompass.ctf.core.CTFException;
a87f8943 36import org.eclipse.tracecompass.ctf.core.CTFStrings;
f357bcd4
AM
37import org.eclipse.tracecompass.ctf.core.event.CTFClock;
38import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
39import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
c8891db9 40import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
f357bcd4 41import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope;
fbe6fa6f 42import org.eclipse.tracecompass.ctf.core.event.scope.ILexicalScope;
15f6223a 43import org.eclipse.tracecompass.ctf.core.event.types.AbstractArrayDefinition;
f357bcd4
AM
44import org.eclipse.tracecompass.ctf.core.event.types.Definition;
45import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
46import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
47import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
48import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
49import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer;
c8891db9 50import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
f357bcd4 51import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
8aa463e0 52import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
1b638236 53import org.eclipse.tracecompass.internal.ctf.core.trace.Utils;
866e5b51
FC
54
55/**
d37aaa7f
FC
56 * A CTF trace on the file system.
57 *
866e5b51
FC
58 * Represents a trace on the filesystem. It is responsible of parsing the
59 * metadata, creating declarations data structures, indexing the event packets
60 * (in other words, all the work that can be shared between readers), but the
61 * actual reading of events is left to TraceReader.
debcffff 62 *
c8891db9
MK
63 * TODO: internalize CTFTrace and DeclarationScope
64 *
866e5b51
FC
65 * @author Matthew Khouzam
66 * @version $Revision: 1.0 $
67 */
b562a24f 68public class CTFTrace implements IDefinitionScope {
866e5b51 69
866e5b51
FC
70 @Override
71 public String toString() {
72 /* Only for debugging, shouldn't be externalized */
a4fa4e36
MK
73 return "CTFTrace [path=" + fPath + ", major=" + fMajor + ", minor=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
74 + fMinor + ", uuid=" + fUuid + "]"; //$NON-NLS-1$ //$NON-NLS-2$
866e5b51
FC
75 }
76
77 /**
78 * The trace directory on the filesystem.
79 */
fe75d403 80 private final File fPath;
866e5b51 81
866e5b51
FC
82 /**
83 * Major CTF version number
84 */
fe75d403 85 private Long fMajor;
866e5b51
FC
86
87 /**
88 * Minor CTF version number
89 */
fe75d403 90 private Long fMinor;
866e5b51
FC
91
92 /**
93 * Trace UUID
94 */
fe75d403 95 private UUID fUuid;
866e5b51
FC
96
97 /**
98 * Trace byte order
99 */
fe75d403 100 private ByteOrder fByteOrder;
866e5b51
FC
101
102 /**
103 * Packet header structure declaration
104 */
fe75d403 105 private StructDeclaration fPacketHeaderDecl = null;
866e5b51 106
1d7277f3
MK
107 /**
108 * The clock of the trace
109 */
ede59fc8 110 private CTFClock fSingleClock = null;
1d7277f3 111
866e5b51
FC
112 /**
113 * Packet header structure definition
debcffff 114 *
866e5b51
FC
115 * This is only used when opening the trace files, to read the first packet
116 * header and see if they are valid trace files.
117 */
fe75d403 118 private StructDefinition fPacketHeaderDef;
866e5b51
FC
119
120 /**
121 * Collection of streams contained in the trace.
122 */
8aa463e0 123 private final Map<Long, ICTFStream> fStreams = new HashMap<>();
866e5b51
FC
124
125 /**
126 * Collection of environment variables set by the tracer
127 */
fe75d403 128 private final Map<String, String> fEnvironment = new HashMap<>();
866e5b51
FC
129
130 /**
131 * Collection of all the clocks in a system.
132 */
fe75d403 133 private final Map<String, CTFClock> fClocks = new HashMap<>();
866e5b51 134
c88e827d 135 /** Handlers for the metadata files */
0594c61c
AM
136 private static final FileFilter METADATA_FILE_FILTER = new MetadataFileFilter();
137 private static final Comparator<File> METADATA_COMPARATOR = new MetadataComparator();
866e5b51 138
c8891db9
MK
139 private final DeclarationScope fScope = new DeclarationScope(null, MetadataStrings.TRACE);
140
866e5b51
FC
141 // ------------------------------------------------------------------------
142 // Constructors
143 // ------------------------------------------------------------------------
144
145 /**
146 * Trace constructor.
debcffff 147 *
866e5b51 148 * @param path
be6df2d8 149 * Filesystem path of the trace directory
680f9173 150 * @throws CTFException
be6df2d8 151 * If no CTF trace was found at the path
866e5b51 152 */
680f9173 153 public CTFTrace(String path) throws CTFException {
866e5b51
FC
154 this(new File(path));
155 }
156
157 /**
158 * Trace constructor.
debcffff 159 *
866e5b51
FC
160 * @param path
161 * Filesystem path of the trace directory.
680f9173 162 * @throws CTFException
be6df2d8 163 * If no CTF trace was found at the path
866e5b51 164 */
680f9173 165 public CTFTrace(File path) throws CTFException {
fe75d403 166 fPath = path;
0594c61c 167 final Metadata metadata = new Metadata(this);
866e5b51 168
c88e827d 169 /* Set up the internal containers for this trace */
fe75d403 170 if (!fPath.exists()) {
680f9173 171 throw new CTFException("Trace (" + path.getPath() + ") doesn't exist. Deleted or moved?"); //$NON-NLS-1$ //$NON-NLS-2$
8a95ce5a 172 }
d0d3aa1b 173
fe75d403 174 if (!fPath.isDirectory()) {
680f9173 175 throw new CTFException("Path must be a valid directory"); //$NON-NLS-1$
d0d3aa1b 176 }
c88e827d
AM
177
178 /* Open and parse the metadata file */
58129ff7 179 metadata.parseFile();
c88e827d 180
58129ff7
MK
181 init(path);
182 }
183
184 /**
185 * Streamed constructor
58129ff7
MK
186 */
187 public CTFTrace() {
fe75d403 188 fPath = null;
58129ff7
MK
189 }
190
680f9173 191 private void init(File path) throws CTFException {
58129ff7 192
58129ff7 193 /* Open all the trace files */
c88e827d
AM
194
195 /* List files not called metadata and not hidden. */
0594c61c
AM
196 File[] files = path.listFiles(METADATA_FILE_FILTER);
197 Arrays.sort(files, METADATA_COMPARATOR);
fe75d403 198
c88e827d 199 /* Try to open each file */
d0d3aa1b
AM
200 for (File streamFile : files) {
201 openStreamInput(streamFile);
c88e827d 202 }
788ddcbc 203
c88e827d 204 /* Create their index */
8aa463e0 205 for (ICTFStream stream : getStreams()) {
d84419e1
AM
206 Set<CTFStreamInput> inputs = stream.getStreamInputs();
207 for (CTFStreamInput s : inputs) {
fe75d403 208 addStream(s);
c88e827d
AM
209 }
210 }
866e5b51
FC
211 }
212
213 // ------------------------------------------------------------------------
214 // Getters/Setters/Predicates
215 // ------------------------------------------------------------------------
216
5f715709
MK
217 /**
218 * Gets an event declaration list for a given streamID
219 *
220 * @param streamId
221 * The ID of the stream from which to read
222 * @return The list of event declarations
5f715709
MK
223 */
224 public Collection<IEventDeclaration> getEventDeclarations(Long streamId) {
8aa463e0 225 ICTFStream stream = fStreams.get(streamId);
202956f1
AM
226 if (stream == null) {
227 return null;
228 }
229 return stream.getEventDeclarations();
5f715709
MK
230 }
231
866e5b51
FC
232 /**
233 * Method getStream gets the stream for a given id
debcffff 234 *
866e5b51
FC
235 * @param id
236 * Long the id of the stream
237 * @return Stream the stream that we need
8aa463e0 238 * @since 2.0
866e5b51 239 */
8aa463e0 240 public ICTFStream getStream(Long id) {
994e0846
MK
241 if (id == null) {
242 return fStreams.get(0L);
243 }
fe75d403 244 return fStreams.get(id);
866e5b51
FC
245 }
246
247 /**
248 * Method nbStreams gets the number of available streams
debcffff 249 *
866e5b51
FC
250 * @return int the number of streams
251 */
252 public int nbStreams() {
fe75d403 253 return fStreams.size();
866e5b51
FC
254 }
255
256 /**
257 * Method setMajor sets the major version of the trace (DO NOT USE)
debcffff 258 *
866e5b51
FC
259 * @param major
260 * long the major version
261 */
262 public void setMajor(long major) {
fe75d403 263 fMajor = major;
866e5b51
FC
264 }
265
266 /**
267 * Method setMinor sets the minor version of the trace (DO NOT USE)
debcffff 268 *
866e5b51
FC
269 * @param minor
270 * long the minor version
271 */
272 public void setMinor(long minor) {
fe75d403 273 fMinor = minor;
866e5b51
FC
274 }
275
276 /**
277 * Method setUUID sets the UUID of a trace
debcffff 278 *
866e5b51
FC
279 * @param uuid
280 * UUID
281 */
282 public void setUUID(UUID uuid) {
fe75d403 283 fUuid = uuid;
866e5b51
FC
284 }
285
286 /**
287 * Method setByteOrder sets the byte order
debcffff 288 *
866e5b51
FC
289 * @param byteOrder
290 * ByteOrder of the trace, can be little-endian or big-endian
291 */
292 public void setByteOrder(ByteOrder byteOrder) {
fe75d403 293 fByteOrder = byteOrder;
866e5b51
FC
294 }
295
296 /**
297 * Method setPacketHeader sets the packet header of a trace (DO NOT USE)
debcffff 298 *
866e5b51
FC
299 * @param packetHeader
300 * StructDeclaration the header in structdeclaration form
301 */
302 public void setPacketHeader(StructDeclaration packetHeader) {
fe75d403 303 fPacketHeaderDecl = packetHeader;
866e5b51
FC
304 }
305
306 /**
07804639 307 * Method majorIsSet is the major version number set?
debcffff 308 *
866e5b51
FC
309 * @return boolean is the major set?
310 */
07804639 311 public boolean majorIsSet() {
fe75d403 312 return fMajor != null;
866e5b51
FC
313 }
314
315 /**
316 * Method minorIsSet. is the minor version number set?
debcffff 317 *
866e5b51
FC
318 * @return boolean is the minor set?
319 */
320 public boolean minorIsSet() {
fe75d403 321 return fMinor != null;
866e5b51
FC
322 }
323
324 /**
325 * Method UUIDIsSet is the UUID set?
debcffff 326 *
866e5b51
FC
327 * @return boolean is the UUID set?
328 */
0594c61c 329 public boolean uuidIsSet() {
fe75d403 330 return fUuid != null;
866e5b51
FC
331 }
332
333 /**
334 * Method byteOrderIsSet is the byteorder set?
debcffff 335 *
866e5b51
FC
336 * @return boolean is the byteorder set?
337 */
338 public boolean byteOrderIsSet() {
fe75d403 339 return fByteOrder != null;
866e5b51
FC
340 }
341
342 /**
343 * Method packetHeaderIsSet is the packet header set?
debcffff 344 *
866e5b51
FC
345 * @return boolean is the packet header set?
346 */
347 public boolean packetHeaderIsSet() {
fe75d403 348 return fPacketHeaderDecl != null;
866e5b51
FC
349 }
350
351 /**
352 * Method getUUID gets the trace UUID
debcffff 353 *
866e5b51
FC
354 * @return UUID gets the trace UUID
355 */
356 public UUID getUUID() {
fe75d403 357 return fUuid;
866e5b51
FC
358 }
359
360 /**
361 * Method getMajor gets the trace major version
debcffff 362 *
866e5b51
FC
363 * @return long gets the trace major version
364 */
365 public long getMajor() {
fe75d403 366 return fMajor;
866e5b51
FC
367 }
368
369 /**
370 * Method getMinor gets the trace minor version
debcffff 371 *
866e5b51
FC
372 * @return long gets the trace minor version
373 */
374 public long getMinor() {
fe75d403 375 return fMinor;
866e5b51
FC
376 }
377
378 /**
379 * Method getByteOrder gets the trace byte order
debcffff 380 *
866e5b51
FC
381 * @return ByteOrder gets the trace byte order
382 */
0594c61c 383 public final ByteOrder getByteOrder() {
fe75d403 384 return fByteOrder;
866e5b51
FC
385 }
386
387 /**
388 * Method getPacketHeader gets the trace packet header
debcffff 389 *
866e5b51
FC
390 * @return StructDeclaration gets the trace packet header
391 */
392 public StructDeclaration getPacketHeader() {
fe75d403 393 return fPacketHeaderDecl;
866e5b51
FC
394 }
395
396 /**
397 * Method getTraceDirectory gets the trace directory
debcffff 398 *
866e5b51
FC
399 * @return File the path in "File" format.
400 */
401 public File getTraceDirectory() {
fe75d403 402 return fPath;
866e5b51
FC
403 }
404
405 /**
f7c5789a 406 * Get all the streams as an iterable.
debcffff 407 *
ab04fc6b 408 * @return Iterable&lt;Stream&gt; an iterable over streams.
866e5b51 409 */
8aa463e0 410 public Iterable<ICTFStream> getStreams() {
fe75d403 411 return fStreams.values();
866e5b51
FC
412 }
413
414 /**
415 * Method getPath gets the path of the trace directory
debcffff 416 *
866e5b51
FC
417 * @return String the path of the trace directory, in string format.
418 * @see java.io.File#getPath()
419 */
866e5b51 420 public String getPath() {
fe75d403 421 return (fPath != null) ? fPath.getPath() : ""; //$NON-NLS-1$
866e5b51
FC
422 }
423
424 // ------------------------------------------------------------------------
425 // Operations
426 // ------------------------------------------------------------------------
427
d84419e1 428 private void addStream(CTFStreamInput s) {
fe75d403
MK
429
430 /*
5f715709 431 * add the stream
fe75d403 432 */
8aa463e0 433 ICTFStream stream = s.getStream();
5f715709 434 fStreams.put(stream.getId(), stream);
fe75d403
MK
435
436 /*
437 * index the trace
438 */
439 s.setupIndex();
440 }
441
866e5b51
FC
442 /**
443 * Tries to open the given file, reads the first packet header of the file
fe75d403 444 * and check its validity. This will add a file to a stream as a streaminput
debcffff 445 *
866e5b51
FC
446 * @param streamFile
447 * A trace file in the trace directory.
26ea03d2
AM
448 * @param index
449 * Which index in the class' streamFileChannel array this file
450 * must use
680f9173 451 * @throws CTFException
fe75d403 452 * if there is a file error
866e5b51 453 */
8aa463e0 454 private ICTFStream openStreamInput(File streamFile) throws CTFException {
f4a474e3 455 ByteBuffer byteBuffer;
866e5b51 456 BitBuffer streamBitBuffer;
8aa463e0 457 ICTFStream stream;
866e5b51
FC
458
459 if (!streamFile.canRead()) {
680f9173 460 throw new CTFException("Unreadable file : " //$NON-NLS-1$
866e5b51
FC
461 + streamFile.getPath());
462 }
a8e1ec04
MK
463 if (streamFile.length() == 0) {
464 return null;
465 }
219d054e 466 try (FileChannel fc = FileChannel.open(streamFile.toPath(), StandardOpenOption.READ)) {
866e5b51 467 /* Map one memory page of 4 kiB */
f4a474e3 468 byteBuffer = SafeMappedByteBuffer.map(fc, MapMode.READ_ONLY, 0, (int) Math.min(fc.size(), 4096L));
b3151232 469 if (byteBuffer == null) {
aefc5c83
MK
470 throw new IllegalStateException("Failed to allocate memory"); //$NON-NLS-1$
471 }
219d054e
MK
472 /* Create a BitBuffer with this mapping and the trace byte order */
473 streamBitBuffer = new BitBuffer(byteBuffer, this.getByteOrder());
219d054e
MK
474 if (fPacketHeaderDecl != null) {
475 /* Read the packet header */
fbe6fa6f 476 fPacketHeaderDef = fPacketHeaderDecl.createDefinition(this, ILexicalScope.PACKET_HEADER, streamBitBuffer);
219d054e 477 }
866e5b51
FC
478 } catch (IOException e) {
479 /* Shouldn't happen at this stage if every other check passed */
680f9173 480 throw new CTFException(e);
866e5b51 481 }
42f8feff
MK
482 final StructDefinition packetHeaderDef = getPacketHeaderDef();
483 if (packetHeaderDef != null) {
484 validateMagicNumber(packetHeaderDef);
866e5b51 485
42f8feff 486 validateUUID(packetHeaderDef);
866e5b51 487
1fbaecd1 488 /* Read the stream ID */
42f8feff 489 IDefinition streamIDDef = packetHeaderDef.lookupDefinition(MetadataStrings.STREAM_ID);
1fbaecd1 490
219d054e
MK
491 if (streamIDDef instanceof IntegerDefinition) {
492 /* This doubles as a null check */
1fbaecd1 493 long streamID = ((IntegerDefinition) streamIDDef).getValue();
fe75d403 494 stream = fStreams.get(streamID);
1fbaecd1
AM
495 } else {
496 /* No stream_id in the packet header */
994e0846 497 stream = getStream(null);
1fbaecd1
AM
498 }
499
866e5b51
FC
500 } else {
501 /* No packet header, we suppose there is only one stream */
994e0846 502 stream = getStream(null);
d0d3aa1b 503 }
866e5b51 504
4311ac8b 505 if (stream == null) {
680f9173 506 throw new CTFException("Unexpected end of stream"); //$NON-NLS-1$
4311ac8b
MAL
507 }
508
8aa463e0
MK
509 if (!(stream instanceof CTFStream)) {
510 throw new CTFException("Stream is not a CTFStream, but rather a " + stream.getClass().getCanonicalName()); //$NON-NLS-1$
511 }
512 CTFStream ctfStream = (CTFStream) stream;
8e15b929
MK
513 /*
514 * Create the stream input and add a reference to the streamInput in the
219d054e 515 * stream.
8e15b929 516 */
8aa463e0
MK
517 ctfStream.addInput(new CTFStreamInput(ctfStream, streamFile));
518 return ctfStream;
866e5b51
FC
519 }
520
680f9173 521 private void validateUUID(StructDefinition packetHeaderDef) throws CTFException {
219d054e 522 IDefinition lookupDefinition = packetHeaderDef.lookupDefinition("uuid"); //$NON-NLS-1$
15f6223a 523 AbstractArrayDefinition uuidDef = (AbstractArrayDefinition) lookupDefinition;
219d054e
MK
524 if (uuidDef != null) {
525 UUID otheruuid = Utils.getUUIDfromDefinition(uuidDef);
526 if (!fUuid.equals(otheruuid)) {
680f9173 527 throw new CTFException("UUID mismatch"); //$NON-NLS-1$
219d054e
MK
528 }
529 }
530 }
531
680f9173 532 private static void validateMagicNumber(StructDefinition packetHeaderDef) throws CTFException {
a87f8943
MK
533 IntegerDefinition magicDef = (IntegerDefinition) packetHeaderDef.lookupDefinition(CTFStrings.MAGIC);
534 if (magicDef != null) {
535 int magic = (int) magicDef.getValue();
536 if (magic != Utils.CTF_MAGIC) {
537 throw new CTFException("CTF magic mismatch"); //$NON-NLS-1$
538 }
219d054e
MK
539 }
540 }
541
708cb26c
MK
542 // ------------------------------------------------------------------------
543 // IDefinitionScope
544 // ------------------------------------------------------------------------
545
fbe6fa6f
MK
546 /**
547 * @since 1.0
548 */
708cb26c 549 @Override
fbe6fa6f
MK
550 public ILexicalScope getScopePath() {
551 return ILexicalScope.TRACE;
708cb26c
MK
552 }
553
866e5b51
FC
554 /**
555 * Looks up a definition from packet
debcffff 556 *
866e5b51
FC
557 * @param lookupPath
558 * String
559 * @return Definition
f357bcd4 560 * @see org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope#lookupDefinition(String)
866e5b51
FC
561 */
562 @Override
563 public Definition lookupDefinition(String lookupPath) {
fbe6fa6f 564 if (lookupPath.equals(ILexicalScope.TRACE_PACKET_HEADER.getPath())) {
42f8feff 565 return getPacketHeaderDef();
866e5b51
FC
566 }
567 return null;
568 }
569
708cb26c
MK
570 // ------------------------------------------------------------------------
571 // Live trace reading
572 // ------------------------------------------------------------------------
573
866e5b51 574 /**
fe75d403
MK
575 * Add a new stream file to support new streams while the trace is being
576 * read.
577 *
578 * @param streamFile
579 * the file of the stream
680f9173 580 * @throws CTFException
fe75d403 581 * A stream had an issue being read
fe75d403 582 */
680f9173 583 public void addStreamFile(File streamFile) throws CTFException {
fe75d403
MK
584 openStreamInput(streamFile);
585 }
586
587 /**
588 * Registers a new stream to the trace.
debcffff 589 *
866e5b51
FC
590 * @param stream
591 * A stream object.
866e5b51 592 * @throws ParseException
be6df2d8 593 * If there was some problem reading the metadata
8aa463e0 594 * @since 2.0
866e5b51 595 */
8aa463e0 596 public void addStream(ICTFStream stream) throws ParseException {
866e5b51
FC
597 /*
598 * If there is already a stream without id (the null key), it must be
599 * the only one
600 */
fe75d403 601 if (fStreams.get(null) != null) {
866e5b51
FC
602 throw new ParseException("Stream without id with multiple streams"); //$NON-NLS-1$
603 }
604
605 /*
a87f8943
MK
606 * If the stream we try to add has no key set, it must be the only one.
607 * Thus, if the streams container is not empty, it is not valid.
866e5b51 608 */
994e0846 609 if ((!stream.isIdSet()) && (!fStreams.isEmpty())) {
866e5b51
FC
610 throw new ParseException("Stream without id with multiple streams"); //$NON-NLS-1$
611 }
612
fe75d403
MK
613 /*
614 * If a stream with the same ID already exists, it is not valid.
615 */
8aa463e0 616 ICTFStream existingStream = fStreams.get(stream.getId());
fe75d403 617 if (existingStream != null) {
866e5b51
FC
618 throw new ParseException("Stream id already exists"); //$NON-NLS-1$
619 }
620
29a7d6ee 621 /* This stream is valid and has a unique id. */
fe75d403 622 fStreams.put(stream.getId(), stream);
866e5b51
FC
623 }
624
9ac2eb62 625 /**
29a7d6ee 626 * Gets the Environment variables from the trace metadata (See CTF spec)
a7297cd3 627 *
a95fddf5
EB
628 * @return The environment variables in the form of an unmodifiable map
629 * (key, value)
9ac2eb62 630 */
791072b0 631 public Map<String, String> getEnvironment() {
fe75d403 632 return Collections.unmodifiableMap(fEnvironment);
866e5b51
FC
633 }
634
9ac2eb62
MK
635 /**
636 * Add a variable to the environment variables
a7297cd3
SD
637 *
638 * @param varName
639 * the name of the variable
640 * @param varValue
641 * the value of the variable
9ac2eb62 642 */
c88e827d 643 public void addEnvironmentVar(String varName, String varValue) {
fe75d403 644 fEnvironment.put(varName, varValue);
866e5b51
FC
645 }
646
9ac2eb62
MK
647 /**
648 * Add a clock to the clock list
a7297cd3
SD
649 *
650 * @param nameValue
651 * the name of the clock (full name with scope)
652 * @param ctfClock
653 * the clock
9ac2eb62 654 */
866e5b51 655 public void addClock(String nameValue, CTFClock ctfClock) {
fe75d403 656 fClocks.put(nameValue, ctfClock);
866e5b51
FC
657 }
658
9ac2eb62
MK
659 /**
660 * gets the clock with a specific name
a7297cd3
SD
661 *
662 * @param name
663 * the name of the clock.
9ac2eb62
MK
664 * @return the clock
665 */
c88e827d 666 public CTFClock getClock(String name) {
fe75d403 667 return fClocks.get(name);
866e5b51
FC
668 }
669
9ac2eb62 670 /**
1d7277f3
MK
671 * gets the clock if there is only one. (this is 100% of the use cases as of
672 * June 2012)
673 *
9ac2eb62
MK
674 * @return the clock
675 */
8ecc80f3 676 public final CTFClock getClock() {
ede59fc8
GB
677 if (fSingleClock != null && fClocks.size() == 1) {
678 return fSingleClock;
679 }
fe75d403
MK
680 if (fClocks.size() == 1) {
681 fSingleClock = fClocks.get(fClocks.keySet().iterator().next());
682 return fSingleClock;
866e5b51
FC
683 }
684 return null;
685 }
686
9ac2eb62
MK
687 /**
688 * gets the time offset of a clock with respect to UTC in nanoseconds
1d7277f3 689 *
9ac2eb62
MK
690 * @return the time offset of a clock with respect to UTC in nanoseconds
691 */
8ecc80f3 692 public final long getOffset() {
c88e827d 693 if (getClock() == null) {
ce2388e0
FC
694 return 0;
695 }
fe75d403 696 return fSingleClock.getClockOffset();
1d7277f3
MK
697 }
698
699 /**
700 * gets the time offset of a clock with respect to UTC in nanoseconds
701 *
702 * @return the time offset of a clock with respect to UTC in nanoseconds
703 */
0594c61c 704 private double getTimeScale() {
1d7277f3
MK
705 if (getClock() == null) {
706 return 1.0;
707 }
fe75d403 708 return fSingleClock.getClockScale();
1d7277f3
MK
709 }
710
962fb72f
PT
711 /**
712 * Gets the current first packet start time
b3151232 713 *
962fb72f 714 * @return the current start time
962fb72f
PT
715 */
716 public long getCurrentStartTime() {
717 long currentStart = Long.MAX_VALUE;
8aa463e0 718 for (ICTFStream stream : fStreams.values()) {
962fb72f 719 for (CTFStreamInput si : stream.getStreamInputs()) {
3f02ac64 720 currentStart = Math.min(currentStart, si.getIndex().getElement(0).getTimestampBegin());
962fb72f
PT
721 }
722 }
723 return timestampCyclesToNanos(currentStart);
724 }
725
726 /**
727 * Gets the current last packet end time
b3151232 728 *
962fb72f 729 * @return the current end time
962fb72f
PT
730 */
731 public long getCurrentEndTime() {
732 long currentEnd = Long.MIN_VALUE;
8aa463e0 733 for (ICTFStream stream : fStreams.values()) {
962fb72f
PT
734 for (CTFStreamInput si : stream.getStreamInputs()) {
735 currentEnd = Math.max(currentEnd, si.getTimestampEnd());
736 }
737 }
738 return timestampCyclesToNanos(currentEnd);
739 }
740
1d7277f3
MK
741 /**
742 * Does the trace need to time scale?
743 *
744 * @return if the trace is in ns or cycles.
745 */
0594c61c 746 private boolean clockNeedsScale() {
1d7277f3
MK
747 if (getClock() == null) {
748 return false;
749 }
fe75d403 750 return fSingleClock.isClockScaled();
1d7277f3
MK
751 }
752
753 /**
754 * the inverse clock for returning to a scale.
755 *
756 * @return 1.0 / scale
757 */
0594c61c 758 private double getInverseTimeScale() {
1d7277f3
MK
759 if (getClock() == null) {
760 return 1.0;
761 }
fe75d403 762 return fSingleClock.getClockAntiScale();
1d7277f3
MK
763 }
764
765 /**
766 * @param cycles
767 * clock cycles since boot
768 * @return time in nanoseconds UTC offset
769 */
770 public long timestampCyclesToNanos(long cycles) {
771 long retVal = cycles + getOffset();
772 /*
773 * this fix is since quite often the offset will be > than 53 bits and
774 * therefore the conversion will be lossy
775 */
776 if (clockNeedsScale()) {
777 retVal = (long) (retVal * getTimeScale());
778 }
779 return retVal;
780 }
781
782 /**
783 * @param nanos
784 * time in nanoseconds UTC offset
785 * @return clock cycles since boot.
786 */
787 public long timestampNanoToCycles(long nanos) {
788 long retVal;
789 /*
790 * this fix is since quite often the offset will be > than 53 bits and
791 * therefore the conversion will be lossy
792 */
793 if (clockNeedsScale()) {
794 retVal = (long) (nanos * getInverseTimeScale());
795 } else {
796 retVal = nanos;
797 }
798 return retVal - getOffset();
ce2388e0
FC
799 }
800
8e15b929
MK
801 /**
802 * Add a new stream
803 *
804 * @param id
805 * the ID of the stream
806 * @param streamFile
807 * new file in the stream
680f9173 808 * @throws CTFException
8e15b929 809 * The file must exist
8e15b929 810 */
680f9173 811 public void addStream(long id, File streamFile) throws CTFException {
b3151232
MK
812 final File file = streamFile;
813 if (file == null) {
680f9173 814 throw new CTFException("cannot create a stream with no file"); //$NON-NLS-1$
b3151232 815 }
8aa463e0 816 ICTFStream stream = fStreams.get(id);
202956f1 817 if (stream == null) {
d84419e1 818 stream = new CTFStream(this);
8e15b929
MK
819 fStreams.put(id, stream);
820 }
8aa463e0
MK
821 if (stream instanceof CTFStream) {
822 CTFStream ctfStream = (CTFStream) stream;
823 ctfStream.addInput(new CTFStreamInput(stream, file));
824 } else {
825 throw new CTFException("Stream does not support adding input"); //$NON-NLS-1$
826 }
8e15b929 827 }
c8891db9
MK
828
829 /**
830 * Gets the current trace scope
831 *
832 * @return the current declaration scope
833 *
0336f981 834 * @since 1.1
c8891db9
MK
835 */
836 public DeclarationScope getScope() {
837 return fScope;
838 }
42f8feff
MK
839
840 /**
841 * Gets the packet header definition (UUID, magic number and such)
842 *
843 * @return the packet header definition
844 *
845 * @since 2.0
846 */
847 public StructDefinition getPacketHeaderDef() {
848 return fPacketHeaderDef;
849 }
866e5b51 850}
c88e827d
AM
851
852class MetadataFileFilter implements FileFilter {
853
854 @Override
855 public boolean accept(File pathname) {
856 if (pathname.isDirectory()) {
857 return false;
858 }
859 if (pathname.isHidden()) {
860 return false;
861 }
862 if (pathname.getName().equals("metadata")) { //$NON-NLS-1$
863 return false;
864 }
865 return true;
866 }
867
868}
869
debcffff 870class MetadataComparator implements Comparator<File>, Serializable {
c88e827d 871
8fd82db5
FC
872 private static final long serialVersionUID = 1L;
873
c88e827d
AM
874 @Override
875 public int compare(File o1, File o2) {
876 return o1.getName().compareTo(o2.getName());
877 }
878}
This page took 0.128117 seconds and 5 git commands to generate.