/// <summary> /// The event header has a variant 'v' that contains one of two structs: /// "compact" or "extended". /// /// In the compact case, the variant tag is used as the event id. /// In the extended case, the extended structure contains an id field. /// </summary> /// <param name="ctfEvent">An event</param> /// <returns>The id of the event</returns> private uint GetEventId(ICtfEvent ctfEvent) { uint id = 0; if (ctfEvent.StreamDefinedEventHeader.FieldType == CtfTypes.Struct) { var streamDefinedEventHeader = ctfEvent.StreamDefinedEventHeader as CtfStructValue; if (streamDefinedEventHeader != null) { foreach (var field in streamDefinedEventHeader.Fields) { if (field.FieldName == "id") { if (uint.TryParse(field.GetValueAsString(), out id)) { return(id); } else { throw new PerfPlaybackException($"Unable to parse event id: {field}"); } } } } } return(id); }
/// <inheritdoc /> public ICtfEventDescriptor GetEventDescriptor( ICtfEvent ctfEvent, ICtfMetadata metadata) { uint id = this.GetEventId(ctfEvent); ICtfEventDescriptor eventDescriptor; if (metadata is PerfMetadata typedMetadata) { // optimization if we get our own metadata back // we'll check this below typedMetadata.EventByEventId.TryGetValue(id, out eventDescriptor); } else { eventDescriptor = metadata.Events.FirstOrDefault(x => x.Id == id); } if (eventDescriptor == null) { throw new PerfPlaybackException($"Unable to find event descriptor for event id={id}."); } return(eventDescriptor); }
public bool PopEvent(out ICtfEvent ctfEvent, out ICtfPacket ctfPacket, out ulong bytesConsumed) { this.dataReadyForConsumption.Wait(this.cancellationToken); this.cancellationToken.ThrowIfCancellationRequested(); lock (this.Events) { if (this.Events.Count == 0) { // we've reached the end of the stream ctfEvent = null; ctfPacket = null; bytesConsumed = 0; return(false); } ctfEvent = this.Events.Dequeue(); ctfPacket = this.Packets.Dequeue(); bytesConsumed = this.BytesProcessed.Dequeue(); if (this.Events.Count == 0 && !this.endOfStream) { this.dataReadyForConsumption.Reset(); } this.readyForNewData.Set(); } return(true); }
public virtual CtfTimestamp GetTimestampFromEventHeader(ICtfEvent ctfEvent, CtfTimestamp previousTimestamp) { var variantStruct = GetStreamEventHeaderStructure(ctfEvent); Debug.Assert(variantStruct != null); if (!variantStruct.FieldsByName.TryGetValue("timestamp", out var timestampValue)) { throw new LTTngPlaybackException("stream.event.header variant 'v' struct has no 'timestamp' field"); } if (!(timestampValue is CtfIntegerValue timestampInteger)) { throw new LTTngPlaybackException("stream.event.header variant 'v' struct field 'timestamp'" + " is not an integer"); } if (previousTimestamp is null) { // todo:I think we need to do something else for this case, especially if the integer size is < 64 // not sure what yet. maybe base it on the clock's offset? return(new CtfTimestamp(this.MetadataCustomization, timestampInteger)); } // Timestamps aren't actually absolute values. To quote from CTF spec 1.8.2 section 8: // For a N-bit integer type referring to a clock, if the integer overflows compared to the N low order bits // of the clock prior value found in the same stream, then it is assumed that one, and only one, overflow // occurred. It is therefore important that events encoding time on a small number of bits happen frequently // enough to detect when more than one N-bit overflow occurs. // So to determine a timestamp, we must know the previous timestamp. If they're all the same number of bits, it // wouldn't be necessary (I don't think so anyways). But some timestamps are smaller than others. if (timestampInteger.Descriptor.Size < 64) { if (!timestampInteger.Value.TryGetInt64(out long thisTimestamp)) { Debug.Assert(false); throw new CtfPlaybackException("Unable to retrieve timestamp as long."); } long previous = (long)previousTimestamp.NanosecondsFromClockBase; long oneBitBeyondBitsUsed = 1L << (byte)timestampInteger.Descriptor.Size; long bitMask = ~(oneBitBeyondBitsUsed - 1); long highBitsFromPreviousTimestamp = previous & bitMask; long newTimestamp = highBitsFromPreviousTimestamp | thisTimestamp; if (newTimestamp < previous) { // handle the overflow case newTimestamp += oneBitBeyondBitsUsed; Debug.Assert(newTimestamp > previous); } return(new CtfTimestamp(this.MetadataCustomization, timestampInteger, newTimestamp)); } return(new CtfTimestamp(this.MetadataCustomization, timestampInteger)); }
public CtfConfigurationPreview(ICtfEvent ctf, IEnumerable <ICountry> countries) { this.Name = ctf.Name; this.Organizers = ctf.Organizers; this.StartTime = ctf.StartTime; this.EndTime = ctf.EndTime; this.Scoring = ctf.Scoring; this.Countries = countries; }
/// <inheritdoc /> public ICtfEventDescriptor GetEventDescriptor( ICtfEvent ctfEvent) { uint id = this.GetEventId(ctfEvent); if (!this.metadataCustomization.LTTngMetadata.EventByEventId.TryGetValue(id, out var eventDescriptor)) { throw new LTTngPlaybackException($"Unable to find event descriptor for event id={id}."); } return(eventDescriptor); }
public CtfPacket(PacketReader packetReader, ICtfEvent previousEvent) { this.packetReader = packetReader; // This is set for the sake of timestamps. The first timestamp in this packet might be // less than 64-bits, and so requires the last timestamp of the stream to complete it. // See CTF specification 1.8.2 section 8 "Clocks" - and read carefully about N-bit integer // types referring to clocks. // this.CurrentEvent = previousEvent; Debug.Assert(this.packetReader.Metadata.TraceDescriptor.PacketHeader != null); }
public void ProcessEvent(ICtfEvent ctfEvent, ICtfPacket eventPacket, ICtfTraceInput traceInput, ICtfInputStream ctfEventStream) { var eventDescriptor = ctfEvent.EventDescriptor as EventDescriptor; Debug.Assert(eventDescriptor != null); if (eventDescriptor == null) { throw new LTTngPlaybackException("EventDescriptor is not an LTTng descriptor."); } if (!this.streamToCpu.TryGetValue(ctfEventStream, out var cpuId)) { var cpuIndex = ctfEventStream.StreamSource.LastIndexOf('_'); string cpu = ctfEventStream.StreamSource.Substring(cpuIndex + 1); if (!uint.TryParse(cpu, out cpuId)) { Debug.Assert(false, "Unable to parse cpu from LTTng stream channel"); cpuId = uint.MaxValue; } this.streamToCpu.Add(ctfEventStream, cpuId); } if (!this.traceContexts.TryGetValue(traceInput, out var traceContext)) { traceContext = new TraceContext(this.metadataCustomization.LTTngMetadata); this.traceContexts.Add(traceInput, traceContext); } var callbackEvent = new LTTngEvent(ctfEvent); var callbackContext = new LTTngContext(this.metadataCustomization, ctfEventStream, traceContext) { // todo: when supporting multiple traces, this timestamp needs to become relative to the earliest timestamp all traces // todo: when supporting multiple traces, this one event number needs to become cumulative across traces, and one specific to the current trace CurrentCpu = cpuId, Timestamp = (long)ctfEvent.Timestamp.NanosecondsFromClockBase,/// - this.baseTimestamp, CurrentEventNumber = this.eventNumber, CurrentEventNumberWithinTrace = this.eventNumber, }; foreach (var callback in this.eventCallbacks) { callback(callbackEvent, callbackContext); } ++this.eventNumber; }
/// <summary> /// The event header has a variant 'v' that contains one of two structs: /// "compact" or "extended". /// /// In the compact case, the variant tag is used as the event id. /// In the extended case, the extended structure contains an id field. /// </summary> /// <param name="ctfEvent">An event</param> /// <returns>The id of the event</returns> private uint GetEventId(ICtfEvent ctfEvent) { var eventHeaderVariant = this.GetStreamEventHeaderVariant(ctfEvent); Debug.Assert(eventHeaderVariant != null); var eventHeaderStruct = GetStreamEventHeaderStructure(eventHeaderVariant); Debug.Assert(eventHeaderStruct != null); uint id = 0; if (StringComparer.InvariantCulture.Equals(eventHeaderStruct.FieldName, "compact")) { if (!eventHeaderVariant.TagEnum.IntegerValue.TryGetUInt32(out id)) { throw new LTTngPlaybackException("stream.event.header.v<tag> - tag value is not a uint."); } return(id); } if (!eventHeaderStruct.FieldsByName.TryGetValue("id", out var idValue)) { throw new LTTngPlaybackException("stream.event.header.v value is not 'id'."); } if (!(idValue is CtfIntegerValue idFieldIntegerValue)) { throw new LTTngPlaybackException("stream.event.header 'id' field is not an integer."); } if (!idFieldIntegerValue.Value.TryGetUInt32(out id)) { throw new LTTngPlaybackException($"stream.event.header.v 'id' is not a uint."); } return(id); }
internal PerfEvent(ICtfEvent ctfEvent) { if (!(ctfEvent.EventDescriptor is IEventDescriptor eventDescriptor)) { throw new CtfPlaybackException("Not a valid Perf event."); } if (ctfEvent.Payload is null) { throw new CtfPlaybackException("Perf event payload is null."); } if (!(ctfEvent.Payload is CtfStructValue payload)) { throw new CtfPlaybackException("Perf event payload is not a structure."); } this.ctfEvent = ctfEvent; this.eventDescriptor = eventDescriptor; /// streamDefinedEventContext }
/// <summary> /// Creates a new instance of the loader. /// </summary> /// <param name="opts">Application configuration.</param> public YamlCtfConfigurationLoader(IOptions <ConfigurationRoot> opts) { var des = new SerializerSettings { ObjectFactory = new YamlObjectFactory() }; des.RegisterSerializerFactory(new YamlTimeSpanConverter()); des.RegisterSerializerFactory(new YamlDateTimeOffsetConverter()); des.RegisterSerializerFactory(new YamlUriConverter()); var deserializer = new Serializer(des); var optv = opts.Value; var fi = new FileInfo(optv.EventConfiguration); using (var fs = fi.OpenRead()) using (var sr = new StreamReader(fs, AbstractionUtilities.UTF8)) { var parser = new Parser(sr); var er = new EventReader(parser); if (er.Expect <StreamStart>() == null) { throw new InvalidDataException("YAML configuration is malformed."); } this._eventConfig = ReadEvent(er, deserializer); this._categories = ReadCategories(er, deserializer); foreach (var cat in this._categories) { foreach (var chall in cat.Challenges) { (chall as YamlCtfChallenge).Category = cat; } } } }
private void PushEvent(ICtfEvent ctfEvent, ICtfPacket ctfPacket, ulong bytesConsumed) { Debug.Assert(ctfEvent != null); Debug.Assert(ctfPacket != null); Debug.Assert(bytesConsumed != 0); this.readyForNewData.Wait(this.cancellationToken); this.cancellationToken.ThrowIfCancellationRequested(); lock (this.Events) { this.Events.Enqueue(ctfEvent); this.Packets.Enqueue(ctfPacket); this.BytesProcessed.Enqueue(bytesConsumed); if (this.Events.Count >= QueueSizeLimit) { this.readyForNewData.Reset(); } this.dataReadyForConsumption.Set(); } }
private CtfVariantValue GetStreamEventHeaderVariant(ICtfEvent ctfEvent) { if (ctfEvent.StreamDefinedEventHeader == null) { throw new LTTngPlaybackException("stream.event.header is not defined"); } if (!(ctfEvent.StreamDefinedEventHeader is CtfStructValue eventHeaderStruct)) { throw new LTTngPlaybackException("stream.event.header is not a structure"); } if (!eventHeaderStruct.FieldsByName.TryGetValue("v", out var variant)) { throw new LTTngPlaybackException("stream.event.header does not contain field 'v'"); } if (!(variant is CtfVariantValue variantValue)) { throw new LTTngPlaybackException("stream.event.header does not field 'v' is not a variant"); } return(variantValue); }
private CtfStructValue GetStreamEventHeaderStructure(ICtfEvent ctfEvent) { var variantValue = this.GetStreamEventHeaderVariant(ctfEvent); return(GetStreamEventHeaderStructure(variantValue)); }