Beispiel #1
0
        public ModuleEvent(LTTngEvent data, LTTngContext context, ExecutingThreadTracker threadTracker)
        {
            this.eventType = ParseEventType(data.Name);

            if (data.Payload.FieldsByName.ContainsKey("_ip"))
            {
                this.instructionPointer = string.Format("0x{0:X}", data.Payload.ReadFieldAsUInt64("_ip"));
            }
            else
            {
                this.instructionPointer = String.Empty;
            }
            if (data.StreamDefinedEventContext != null && data.StreamDefinedEventContext.FieldsByName.ContainsKey("_tid"))
            {
                this.tid = data.StreamDefinedEventContext.ReadFieldAsInt32("_tid");
            }
            else
            {
                this.tid = threadTracker.CurrentTidAsInt(context.CurrentCpu);
            }
            this.threadId = this.tid.ToString();
            if (data.Payload.FieldsByName.ContainsKey("_refcnt"))
            {
                this.refCount = data.Payload.ReadFieldAsInt32("_refcnt");
            }
            else
            {
                this.refCount = 0;
            }

            this.moduleName = data.Payload.FieldsByName["_name"].GetValueAsString();
            this.time       = data.Timestamp;
        }
 public override DataProcessingResult CookDataElement(LTTngEvent data, LTTngContext context, CancellationToken cancellationToken)
 {
     try
     {
         if (this.discardedEventsTracker.EventsDiscardedBetweenLastTwoEvents(data, context) > 0)
         {
             this.discardedEventsTimestamps.Add(data.Timestamp);
             this.threadTracker.ReportEventsDiscarded(context.CurrentCpu);
         }
         this.threadTracker.ProcessEvent(data, context);
         if (data.Name.StartsWith("syscall") || LTTngSyscallDataCooker.UknownSyscallExit.Equals(data.Name))
         {
             this.ProcessSyscall(new SyscallEvent(data, context, this.threadTracker));
             return(DataProcessingResult.Processed);
         }
         else
         {
             return(DataProcessingResult.Ignored);
         }
     }
     catch (CtfPlaybackException e)
     {
         Console.Error.WriteLine(e);
         return(DataProcessingResult.CorruptData);
     }
 }
        public override DataProcessingResult CookDataElement(
            LTTngEvent data,
            LTTngContext context,
            CancellationToken cancellationToken)
        {
            try
            {
                ContextSwitchUserData parsed = ContextSwitchUserData.Read(data.Payload);

                ContextSwitches.AddEvent(
                    new ContextSwitch(
                        data.Timestamp,
                        parsed.PrevComm,
                        parsed.PrevTid,
                        parsed.PrevPrio,
                        parsed.NextComm,
                        parsed.NextTid,
                        parsed.NextPrio));
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e);
                return(DataProcessingResult.CorruptData);
            }

            return(DataProcessingResult.Processed);
        }
Beispiel #4
0
 public override DataProcessingResult CookDataElement(LTTngEvent data, LTTngContext context, CancellationToken cancellationToken)
 {
     try
     {
         if (this.discardedEventsTracker.EventsDiscardedBetweenLastTwoEvents(data, context) > 0)
         {
             this.threadTracker.ReportEventsDiscarded(context.CurrentCpu);
         }
         this.threadTracker.ProcessEvent(data, context);
         if (data.Name.StartsWith("module"))
         {
             this.moduleEvents.Add(new ModuleEvent(data, context, this.threadTracker));
             return(DataProcessingResult.Processed);
         }
         else
         {
             return(DataProcessingResult.Ignored);
         }
     }
     catch (CtfPlaybackException e)
     {
         Console.Error.WriteLine(e);
         return(DataProcessingResult.CorruptData);
     }
 }
        private void ProcessDiagnosticMessage(LTTngEvent data)
        {
            string    logLine           = data.Payload.FieldsByName["_msg"].GetValueAsString();
            Timestamp timestamp         = data.Timestamp;
            string    message           = logLine;
            int       messageStartIndex = 1;

            while (messageStartIndex < logLine.Length && logLine[messageStartIndex] != ']')
            {
                ++messageStartIndex;
            }
            if (messageStartIndex > 1 && messageStartIndex < logLine.Length)
            {
                if (Double.TryParse(logLine.Substring(1, messageStartIndex - 1), out double timestampDouble))
                {
                    timestamp = new Timestamp((long)(timestampDouble * 1000000000.0));
                }
                if (messageStartIndex < logLine.Length - 1 && logLine[messageStartIndex + 1] == ' ')
                {
                    ++messageStartIndex;
                }
                message = logLine.Substring(messageStartIndex);
            }
            this.diagnosticMessages.Add(new DiagnosticMessage(message, timestamp));
        }
        public LTTngGenericEvent(LTTngEvent data, LTTngContext context)
        {
            if (!(data.Payload is CtfStructValue payload))
            {
                throw new CtfPlaybackException("Event data is corrupt.");
            }

            this.Timestamp       = data.Timestamp;
            this.CpuId           = context.CurrentCpu;
            this.DiscardedEvents = data.DiscardedEvents;

            if (!EventKind.RegisteredKinds.TryGetValue(data.Id, out this.kind))
            {
                this.kind = new EventKind(data.Id, data.Name, payload.Fields);
                EventKind.RegisteredKinds.Add(data.Id, this.kind);
            }

            // As this is being written, all columns are of type 'T', so all rows are the same. For generic events,
            // where columns have different types for different rows, this means everything becomes a string.
            //
            // We don't want to keep around each event in memory, that would use too much memory. So for now convert
            // each field value to a string, which would happen anyways.
            //
            // If the consumer is smarter in the future and allows for multi-type columns, we can re-evaluate this
            // approach. We could probably generate a type from each event descriptor, and convert to that type.
            //

            this.FieldValues = new List <string>(payload.Fields.Count);
            foreach (var field in payload.Fields)
            {
                this.FieldValues.Add(field.GetValueAsString());
            }
        }
Beispiel #7
0
        public void ProcessThreadCloneSyscallEntry(LTTngEvent data, LTTngContext context)
        {
            ThreadInfo threadInExecution = this.EventCreatorThread(data, context.CurrentCpu);

            if (threadInExecution != null)
            {
                if (this.closingEventsToBeSkipped.TryGetValue(threadInExecution.Tid, out int eventsToBeSkipped) && eventsToBeSkipped > 0)
                {
                    this.closingEventsToBeSkipped[threadInExecution.Tid] = eventsToBeSkipped + 1;
                    return;
                }
                uint flags = data.Payload.ReadFieldAsUInt32("_clone_flags");
                if (cloneSyscallFlagsPerTid.TryGetValue(threadInExecution.Tid, out Dictionary <uint, int> lastCalls))
                {
                    if (lastCalls.TryGetValue(flags, out int timesUsed))
                    {
                        lastCalls[flags] = timesUsed + 1;
                    }
                    else
                    {
                        lastCalls[flags] = 1;
                    }
                }
                else
                {
                    cloneSyscallFlagsPerTid[threadInExecution.Tid] = new Dictionary <uint, int>()
                    {
                        [flags] = 1
                    };
                }
            }
        }
 private ThreadInfo EventCreatorThread(LTTngEvent data, uint cpu)
 {
     if (data.StreamDefinedEventContext != null && data.StreamDefinedEventContext.FieldsByName.ContainsKey("_tid") &&
         runningThreads.TryGetValue(data.StreamDefinedEventContext.ReadFieldAsInt32("_tid"), out ThreadInfo callerThread))
     {
         return(callerThread);
     }
     return(this.CurrentExecutingThread(cpu));
 }
        public void ProcessThreadExit(LTTngEvent data)
        {
            int tid = data.Payload.ReadFieldAsInt32("_tid");

            if (runningThreads.TryGetValue(tid, out ThreadInfo exitingThread))
            {
                exitingThread.Terminate(data.Timestamp);
            }
        }
        void ProcessStatedump(LTTngEvent data)
        {
            int tid = data.Payload.ReadFieldAsInt32("_tid");

            if (data.StreamDefinedEventContext != null && this.runningThreads.TryGetValue(tid, out ThreadInfo thread))
            {
                this.ProcessThreadMetadata(data, thread);
            }
        }
 public void ProcessEvent(LTTngEvent data, LTTngContext context)
 {
     if (ContextSwitchEventName.Equals(data.Name))
     {
         while (this.executingThreadPerCpu.Count <= context.CurrentCpu)
         {
             this.executingThreadPerCpu.Add(-1);
         }
         this.executingThreadPerCpu[(int)context.CurrentCpu] = data.Payload.ReadFieldAsInt32("_next_tid");
     }
 }
        void ProcessSyscallEventMetadata(LTTngEvent data)
        {
            int        tid = data.StreamDefinedEventContext.ReadFieldAsInt32("_tid");
            ThreadInfo callerThread;

            if (!this.runningThreads.TryGetValue(tid, out callerThread))
            {
                callerThread = new ThreadInfo(tid, data.Timestamp, ThreadInfo.ThreadState.TASK_RUNNING);
                this.AddNewThread(callerThread);
            }

            this.ProcessThreadMetadata(data, callerThread);
        }
 public SyscallEvent(LTTngEvent data, LTTngContext context, ExecutingThreadTracker threadTracker)
 {
     this.name      = EventNameToSyscallName(data.Name, out this.isEntry);
     this.timestamp = data.Timestamp;
     this.fields    = data.Payload.FieldsByName;
     if (data.StreamDefinedEventContext != null && data.StreamDefinedEventContext.FieldsByName.ContainsKey("_tid"))
     {
         this.tid = data.StreamDefinedEventContext.ReadFieldAsInt32("_tid");
     }
     else
     {
         this.tid = threadTracker.CurrentTidAsInt(context.CurrentCpu);
     }
 }
 public void SwitchOut(LTTngEvent data, ThreadState newState)
 {
     this.ExecTimeNs           += data.Timestamp - this.lastEventTimestamp;
     this.currentState          = ThreadStateToSchedulingState(newState);
     this.previousState         = SchedulingState.Running;
     this.lastEventTimestamp    = data.Timestamp;
     this.previousSwitchOutTime = data.Timestamp;
     this.readyingPid           = String.Empty;
     this.readyingTid           = String.Empty;
     if (this.isTerminated())
     {
         this.ExitTime = data.Timestamp;
     }
 }
        public void ProcessThreadWakeUp(LTTngEvent data, LTTngContext context)
        {
            int tid = data.Payload.ReadFieldAsInt32("_tid");

            if (runningThreads.TryGetValue(tid, out ThreadInfo nextThread))
            {
                nextThread.Wakeup(data.Timestamp);
            }
            else
            {
                ThreadInfo readyingThread = this.EventCreatorThread(data, context.CurrentCpu);
                this.AddNewThread(new ThreadInfo(tid, data.Timestamp, ThreadInfo.ThreadState.TASK_RUNNING, readyingThread));
            }
        }
        public void ProcessThreadCloneSyscallEntry(LTTngEvent data, LTTngContext context)
        {
            ThreadInfo threadInExecution = this.EventCreatorThread(data, context.CurrentCpu);

            if (threadInExecution != null)
            {
                if (this.closingEventsToBeSkipped.TryGetValue(threadInExecution.Tid, out int eventsToBeSkipped) && eventsToBeSkipped > 0)
                {
                    this.closingEventsToBeSkipped[threadInExecution.Tid] = eventsToBeSkipped + 1;
                    return;
                }

                uint?        cloneFlags           = null;
                const string SysCallCloneFlags    = "_clone_flags";
                const string SysCallFlagsAsStruct = "_flags";  // https://lttng.org/docs/v2.13/#doc-whats-new & https://github.com/lttng/lttng-modules/commit/d775625e2ba4825b73b5897e7701ad6e2bdba115

                if (data.Payload.FieldsByName.ContainsKey(SysCallCloneFlags))
                {
                    cloneFlags = data.Payload.ReadFieldAsUInt32(SysCallCloneFlags);
                }
                else if (data.Payload.FieldsByName.ContainsKey(SysCallFlagsAsStruct)) // New since v2.13
                {
                    var flags = data.Payload.ReadFieldAsUInt32(SysCallFlagsAsStruct);
                    // var exitSignal = flags & 0xFF;   // the least significant byte of the `unsigned long` is the signal the kernel need to send to the parent process on child exit
                    cloneFlags = flags & 0xFFFFFF00; // the remaining bytes of the `unsigned long` is used a bitwise flag for the clone options.
                }

                if (cloneFlags.HasValue)
                {
                    if (cloneSyscallFlagsPerTid.TryGetValue(threadInExecution.Tid, out Dictionary <uint, int> lastCalls))
                    {
                        if (lastCalls.TryGetValue(cloneFlags.Value, out int timesUsed))
                        {
                            lastCalls[cloneFlags.Value] = timesUsed + 1;
                        }
                        else
                        {
                            lastCalls[cloneFlags.Value] = 1;
                        }
                    }
                    else
                    {
                        cloneSyscallFlagsPerTid[threadInExecution.Tid] = new Dictionary <uint, int>()
                        {
                            [cloneFlags.Value] = 1
                        };
                    }
                }
            }
        }
        private void ProcessEventDrop(LTTngEvent data, LTTngContext context)
        {
            uint discardedEventsBetweenLastTwoEvents = this.discardedEventsTracker.EventsDiscardedBetweenLastTwoEvents(data, context);

            if (discardedEventsBetweenLastTwoEvents > 0)
            {
                if (this.lastContextSwitch.TryGetValue(context.CurrentCpu, out ContextSwitch lastContextSwitchOnCpu))
                {
                    processedExecutionEvents.Add(new ExecutionEvent(lastContextSwitchOnCpu, lastContextSwitchOnCpu.SwitchInTime));
                    this.lastContextSwitch.Remove(context.CurrentCpu);
                }
                this.cloneSyscallFlagsPerTid.Clear();
                this.closingEventsToBeSkipped.Clear();
            }
        }
Beispiel #18
0
        public uint EventsDiscardedBetweenLastTwoEvents(LTTngEvent data, LTTngContext context)
        {
            while (this.discardedEventsPerCpu.Count <= context.CurrentCpu)
            {
                this.discardedEventsPerCpu.Add(0);
            }
            uint previousDiscardedEvents = this.discardedEventsPerCpu[(int)context.CurrentCpu];

            if (previousDiscardedEvents < data.DiscardedEvents)
            {
                discardedEventsPerCpu[(int)context.CurrentCpu] = data.DiscardedEvents;
                return(data.DiscardedEvents - previousDiscardedEvents);
            }
            return(0);
        }
 private void ProcessGetPidSyscallExit(LTTngEvent data, LTTngContext context)
 {
     if (data.StreamDefinedEventContext == null ||
         !data.StreamDefinedEventContext.FieldsByName.ContainsKey("_pid") ||
         !data.StreamDefinedEventContext.FieldsByName.ContainsKey("_tid"))
     {
         ///This heuristic is activated when the event context does not have metadata regarding to tid and pid
         ThreadInfo executingThread = CurrentExecutingThread(context.CurrentCpu);
         int        pid             = data.Payload.ReadFieldAsInt32("_ret");
         if (executingThread != null && executingThread.Pid < 0)
         {
             this.RecoverPid(executingThread, pid);
         }
     }
 }
        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;
        }
 public override DataProcessingResult CookDataElement(LTTngEvent data, LTTngContext context, CancellationToken cancellationToken)
 {
     try
     {
         if (DmesgDataKey.Equals(data.Name))
         {
             ProcessDiagnosticMessage(data);
             return(DataProcessingResult.Processed);
         }
         else
         {
             return(DataProcessingResult.Ignored);
         }
     }
     catch (CtfPlaybackException e)
     {
         Console.Error.WriteLine(e);
         return(DataProcessingResult.CorruptData);
     }
 }
        public override DataProcessingResult CookDataElement(
            LTTngEvent data,
            LTTngContext context,
            CancellationToken cancellationToken)
        {
            try
            {
                Events.AddEvent(new LTTngGenericEvent(data, context));

                this.MaximumEventFieldCount =
                    Math.Max(data.Payload.Fields.Count, this.MaximumEventFieldCount);
            }
            catch (CtfPlaybackException e)
            {
                Console.Error.WriteLine($"Error consuming event: {e.Message}");
                return(DataProcessingResult.CorruptData);
            }

            return(DataProcessingResult.Processed);
        }
        public void ProcessSchedForkEvent(LTTngEvent data, LTTngContext context)
        {
            int newTid = data.Payload.ReadFieldAsInt32("_child_tid");

            if (runningThreads.TryGetValue(newTid, out ThreadInfo oldThreadWithSamePid))
            {
                this.terminatedThreads.Add(new Thread(oldThreadWithSamePid));
            }

            ThreadInfo parentThread = null;
            int        parentTid    = data.Payload.ReadFieldAsInt32("_parent_tid");

            if (runningThreads.ContainsKey(parentTid))
            {
                parentThread = runningThreads[parentTid];
                if (parentThread.Pid < 0)
                {
                    this.RecoverPid(parentThread, data.Payload.ReadFieldAsInt32("_parent_pid"));
                }
            }
            this.AddNewThread(new ThreadInfo(newTid, data.Timestamp, ThreadInfo.ThreadState.TASK_NEW, parentThread));
        }
 public ContextSwitch(LTTngEvent data, ThreadInfo nextThread, ThreadInfo previousThread, uint cpu)
 {
     this.cpu         = cpu;
     this.nextPid     = nextThread.PidAsString();
     this.nextTid     = nextThread.Tid;
     this.previousPid = previousThread.PidAsString();
     this.previousTid = previousThread.Tid;
     this.priority    = data.Payload.ReadFieldAsInt32("_next_prio");
     if (nextThread.currentState == ThreadInfo.SchedulingState.Running)
     {
         this.readyingPid   = nextThread.readyingPid;
         this.readyingTid   = nextThread.readyingTid;
         this.readyTime     = data.Timestamp - nextThread.lastEventTimestamp;
         this.previousState = ThreadInfo.SchedulingStateToString(nextThread.previousState);
         if (nextThread.previousState == ThreadInfo.SchedulingState.Running ||
             nextThread.previousState == ThreadInfo.SchedulingState.NewlyCreated ||
             nextThread.previousState == ThreadInfo.SchedulingState.Unknown)
         {
             this.waitTime = new TimestampDelta(0);
         }
         else
         {
             this.waitTime = nextThread.previousWaitTime;
         }
     }
     else
     {
         this.readyingPid   = string.Empty;
         this.readyingTid   = string.Empty;
         this.readyTime     = new TimestampDelta(0);
         this.waitTime      = data.Timestamp - nextThread.lastEventTimestamp;
         this.previousState = ThreadInfo.SchedulingStateToString(nextThread.currentState);
     }
     this.nextCommand     = data.Payload.ReadFieldAsArray("_next_comm").GetValueAsString();
     this.previousCommand = data.Payload.ReadFieldAsArray("_prev_comm").GetValueAsString();
     this.switchInTime    = data.Timestamp;
     this.nextThreadPreviousSwitchOutTime = nextThread.previousSwitchOutTime;
 }
        void ProcessThreadMetadata(LTTngEvent data, ThreadInfo thread)
        {
            if (data.StreamDefinedEventContext.FieldsByName.ContainsKey("_pid"))
            {
                int pid = data.StreamDefinedEventContext.ReadFieldAsInt32("_pid");
                if (thread.Pid != pid)
                {
                    this.RecoverPid(thread, pid);
                }
            }

            if (thread.Command.Equals(String.Empty))
            {
                if (data.StreamDefinedEventContext.FieldsByName.ContainsKey("_procname"))
                {
                    thread.Command = data.StreamDefinedEventContext.ReadFieldAsArray("_procname").ReadAsString();
                }
                else if (data.StreamDefinedEventContext.FieldsByName.ContainsKey("_name"))
                {
                    thread.Command = data.StreamDefinedEventContext.ReadFieldAsArray("_name").ReadAsString();
                }
            }
        }
        private void ProcessThreadExec(LTTngEvent data)
        {
            var filepath = data.Payload.ReadFieldAsString("_filename").GetValueAsString().Split('/');

            if (filepath.Length > 0)
            {
                string command = filepath[filepath.Length - 1];

                int tid = data.Payload.ReadFieldAsInt32("_tid");
                if (!this.runningThreads.TryGetValue(tid, out ThreadInfo runningThread))
                {
                    this.AddNewThread(new ThreadInfo(tid, data.Timestamp, ThreadInfo.ThreadState.TASK_RUNNING));
                }
                else if (runningThread.ExecTimeNs.ToMilliseconds > 10)
                {
                    ///if it is not a fork + execv, we terminate the old thread
                    runningThread.Terminate(data.Timestamp);
                    this.terminatedThreads.Add(new Thread(runningThread));
                    this.AddNewThread(new ThreadInfo(tid, data.Timestamp, ThreadInfo.ThreadState.TASK_RUNNING, runningThread, true));
                }
                runningThreads[tid].Command = command;
            }
        }
        public override DataProcessingResult CookDataElement(LTTngEvent data, LTTngContext context, CancellationToken cancellationToken)
        {
            this.lastEventTimestamp = data.Timestamp;
            this.ProcessEventDrop(data, context);
            var result = DataProcessingResult.Ignored;

            try
            {
                if (data.Name.StartsWith("syscall") && this.EventHasMetadata(data))
                {
                    this.ProcessSyscallEventMetadata(data);
                    result = DataProcessingResult.Processed;
                }
                switch (data.Name)
                {
                case SchedulerDataKeys.Switch:
                    this.ProcessContextSwitch(data, context);
                    return(DataProcessingResult.Processed);

                case SchedulerDataKeys.Wakeup:
                case SchedulerDataKeys.NewWakeup:
                    this.ProcessThreadWakeUp(data, context);
                    return(DataProcessingResult.Processed);

                case SchedulerDataKeys.Waking:
                    this.ProcessThreadWaking(data, context);
                    return(DataProcessingResult.Processed);

                case SchedulerDataKeys.ProcessFork:
                    this.ProcessSchedForkEvent(data, context);
                    return(DataProcessingResult.Processed);

                case SchedulerDataKeys.ProcessExit:
                    this.ProcessThreadExit(data);
                    return(DataProcessingResult.Processed);

                case SchedulerDataKeys.ProcessExec:
                    this.ProcessThreadExec(data);
                    return(DataProcessingResult.Processed);

                case ThreadCreationDataKeys.CloneEntry:
                    this.ProcessThreadCloneSyscallEntry(data, context);
                    return(DataProcessingResult.Processed);

                case ThreadCreationDataKeys.CloneExit:
                    this.ProcessThreadCloneSyscallExit(data, context);
                    return(DataProcessingResult.Processed);

                case LTTngThreadDataCooker.GetPidExit:
                    this.ProcessGetPidSyscallExit(data, context);
                    return(DataProcessingResult.Processed);

                case StatedumpDataKeys.ProcessState:
                    this.ProcessStatedump(data);
                    return(DataProcessingResult.Processed);
                }
            }
            catch (CtfPlaybackException e)
            {
                Console.Error.WriteLine(e);
                return(DataProcessingResult.CorruptData);
            }

            return(result);
        }
        public void ProcessThreadCloneSyscallExit(LTTngEvent data, LTTngContext context)
        {
            int newThreadTid = data.Payload.ReadFieldAsInt32("_ret");

            if (newThreadTid == 0)
            {
                ///This is the returning syscall for the newly created child
                return;
            }
            ThreadInfo threadInExecution = this.EventCreatorThread(data, context.CurrentCpu);

            if (threadInExecution != null)
            {
                if (this.closingEventsToBeSkipped.TryGetValue(threadInExecution.Tid, out int eventsToBeSkipped) && eventsToBeSkipped > 0)
                {
                    if (eventsToBeSkipped == 1)
                    {
                        this.closingEventsToBeSkipped.Remove(threadInExecution.Tid);
                    }
                    else
                    {
                        this.closingEventsToBeSkipped[threadInExecution.Tid] = eventsToBeSkipped - 1;
                    }
                }
                else if (cloneSyscallFlagsPerTid.TryGetValue(threadInExecution.Tid, out Dictionary <uint, int> lastCalls))
                {
                    if (lastCalls.Count == 1)
                    {
                        uint flag = new List <uint>(lastCalls.Keys)[0];
                        if (newThreadTid > 0 && (flag & 0x00010000) > 0 && runningThreads.TryGetValue(threadInExecution.Tid, out ThreadInfo parentThread))
                        {
                            if (runningThreads.TryGetValue(newThreadTid, out ThreadInfo newThread))
                            {
                                newThread.Pid = parentThread.Pid;
                            }
                            else
                            {
                                this.AddNewThread(new ThreadInfo(newThreadTid, data.Timestamp, ThreadInfo.ThreadState.TASK_NEW, threadInExecution, true));
                            }
                        }

                        int amountOfEntries = lastCalls[flag];
                        if (amountOfEntries <= 1)
                        {
                            lastCalls.Remove(flag);
                        }
                        else
                        {
                            lastCalls[flag] = amountOfEntries - 1;
                        }
                    }
                    else if (lastCalls.Count > 1)
                    {
                        int pendingEntryEvents = 0;
                        foreach (var entry in lastCalls)
                        {
                            pendingEntryEvents += entry.Value;
                        }
                        closingEventsToBeSkipped[threadInExecution.Tid] = pendingEntryEvents - 1; ///Decrease one for the current closing event
                        lastCalls.Clear();
                    }
                }
            }
        }
 bool EventHasMetadata(LTTngEvent data)
 {
     return(data.StreamDefinedEventContext != null && data.StreamDefinedEventContext.FieldsByName.ContainsKey("_tid") &&
            (data.StreamDefinedEventContext.FieldsByName.ContainsKey("_pid") || data.StreamDefinedEventContext.FieldsByName.ContainsKey("_procname")));
 }
        public void ProcessContextSwitch(LTTngEvent data, LTTngContext context)
        {
            int prevTid = data.Payload.ReadFieldAsInt32("_prev_tid");

            if (lastContextSwitch.TryGetValue(context.CurrentCpu, out ContextSwitch previousContextSwitch))
            {
                if (prevTid == previousContextSwitch.NextTid)
                {
                    processedExecutionEvents.Add(new ExecutionEvent(previousContextSwitch, data.Timestamp));
                }
                else
                {
                    ///If we missed context switch events,
                    processedExecutionEvents.Add(new ExecutionEvent(previousContextSwitch, previousContextSwitch.SwitchInTime));
                }
            }
            int nextTid = data.Payload.ReadFieldAsInt32("_next_tid");

            ThreadInfo.ThreadState switchOutState;
            var prevStateValue = data.Payload.FieldsByName["_prev_state"];

            if (prevStateValue.FieldType == CtfTypes.Enum)
            {
                ((CtfEnumValue)prevStateValue).IntegerValue.TryGetInt32(out int enumValue);
                switchOutState = (ThreadInfo.ThreadState)enumValue;
            }
            else
            {
                switchOutState = (ThreadInfo.ThreadState)data.Payload.ReadFieldAsInt32("_prev_state");
            }

            ThreadInfo prevThread;

            if (runningThreads.TryGetValue(prevTid, out prevThread))
            {
                prevThread.SwitchOut(data, switchOutState);
            }
            else
            {
                prevThread = new ThreadInfo(prevTid, data.Timestamp, switchOutState);
                this.AddNewThread(prevThread);
            }

            if (this.EventHasMetadata(data))
            {
                this.ProcessThreadMetadata(data, prevThread);
            }

            ThreadInfo nextThread;

            if (runningThreads.TryGetValue(nextTid, out nextThread))
            {
                lastContextSwitch[context.CurrentCpu] = new ContextSwitch(data, nextThread, prevThread, context.CurrentCpu);
                nextThread.SwitchIn(data.Timestamp);
            }
            else
            {
                nextThread = new ThreadInfo(nextTid, data.Timestamp, ThreadInfo.ThreadState.TASK_RUNNING);
                lastContextSwitch[context.CurrentCpu] = new ContextSwitch(data, nextThread, prevThread, context.CurrentCpu);
                this.AddNewThread(nextThread);
            }
        }