private IList <CtfStreamPlayback> GeneratePlaybackStreams(ICtfInput source, CtfPlaybackOptions playbackOptions) { var playbackStreams = new List <CtfStreamPlayback>(); // Initialize packets from all streams, and sort by times foreach (var trace in source.Traces) { var metadataParser = customization.CreateMetadataParser(trace); ICtfMetadata metadata = metadataParser.Parse(trace.MetadataStream.Stream); for (int streamIndex = 0; streamIndex < trace.EventStreams.Count; streamIndex++) { var stream = trace.EventStreams[streamIndex]; var eventStream = new CtfEventStream(stream, metadata, customization); var streamPlayback = new CtfStreamPlayback(eventStream, playbackOptions, cancellationToken); if (eventStream.ByteCount > 0 && streamPlayback.MoveToNextEvent()) { Debug.Assert(streamPlayback.CurrentEvent != null); playbackStreams.Add(streamPlayback); this.streamToTrace.Add(streamPlayback, trace); this.totalBytesToProcess += stream.ByteCount; } else { Debug.Assert(false, eventStream.StreamSource + " appears to have no data.\n\n Ignoring the error will cause the trace to be partially loaded."); } } } return(playbackStreams); }
/// <summary> /// Playback the events in time order. Event callbacks happen through ICtfPlaybackCustomization.ProcessEvent, /// allowing for customized event delivery. /// </summary> /// <param name="source">CTF trace input source</param> /// <param name="playbackOptions">Playback options</param> /// <param name="progress">Progress meter</param> public void Playback( ICtfInput source, CtfPlaybackOptions playbackOptions, IProgress <byte> progress) { Guard.NotNull(source, nameof(source)); Guard.NotNull(progress, nameof(progress)); var playbackStreams = GeneratePlaybackStreams(source, playbackOptions); while (playbackStreams.Any()) { // Find the event stream with the earlieste available event. CtfStreamPlayback streamPlayback = playbackStreams[0]; for (int x = 1; x < playbackStreams.Count; x++) { if (playbackStreams[x].CurrentEvent.Timestamp.NanosecondsFromPosixEpoch < streamPlayback.CurrentEvent.Timestamp.NanosecondsFromPosixEpoch) { streamPlayback = playbackStreams[x]; } } if (streamPlayback.CurrentEvent.Timestamp.NanosecondsFromPosixEpoch < this.lastEventTimestamp) { Debug.Assert(false, "time inversion?"); Console.Error.WriteLine("Time inversion discovered in LTTng trace."); } this.customization.ProcessEvent( streamPlayback.CurrentEvent, streamPlayback.CurrentPacket, this.streamToTrace[streamPlayback], streamPlayback.EventStream, streamPlayback.Metadata); this.eventCount++; this.lastEventTimestamp = streamPlayback.CurrentEvent.Timestamp.NanosecondsFromPosixEpoch; if (!streamPlayback.MoveToNextEvent()) { playbackStreams.Remove(streamPlayback); this.bytesProcessedFromCompletedStreams += streamPlayback.EventStream.ByteCount; } if (this.eventCount - this.lastProgressUpdateTimeEventNumber >= 5000) { this.UpdateProgress(playbackStreams, progress); } this.cancellationToken.ThrowIfCancellationRequested(); } this.UpdateProgress(playbackStreams, progress); }
public CtfStreamPlayback( ICtfEventStream eventStream, CtfPlaybackOptions playbackOptions, CancellationToken cancellationToken) { Debug.Assert(eventStream != null); Debug.Assert(cancellationToken != null); this.cancellationToken = cancellationToken; this.EventStream = eventStream; this.useReadAhead = playbackOptions.ReadAhead; }