Exemplo n.º 1
0
        // Called when we enter the circular part of the log and the thread's true call stack
        // (logged with each thread's first record in each block) is read from the log.
        // This is enough info to generate replacement entry/exit records that were lost when
        // the log wrapped, but whose counterparts were not lost.
        internal void MakeMissingRecords(ReaderStackEntry[] circularStack)
        {
            if (NonCircularStack != null)
            {
                MissingEntryRecords = new List <Record>();
                MissingExitRecords  = new List <Record>();

                // The deepest entry comes last in circularStack.
                int trueDepth = circularStack == null ? 0 : circularStack.Length;

                // If the true stack depth is greater than the stack depth we got
                // by pushing MehtodEntry records and popping MethodExit records,
                // we must generate the missing MethodEntry records.
                while (trueDepth > NonCircularStack.Count)
                {
                    // This constructs an entry record.
                    MissingEntryRecords.Add(new Record(this, circularStack[--trueDepth]));
                }

                // If the true stack depth is less than the stack depth we got
                // by pushing MehtodEntry records and popping MethodExit records,
                // we must generate the missing MethodExit records.
                while (trueDepth < NonCircularStack.Count)
                {
                    // This constructs an exit record.
                    MissingExitRecords.Add(new Record(NonCircularStack.Pop()));
                }

                // Now the two stacks are the same depth.
                // Wherever two entries don't match, we are missing
                // both an entry and an exit record.
                while (NonCircularStack.Count > 0)
                {
                    Record           parsedEntry = NonCircularStack.Pop();
                    ReaderStackEntry trueEntry   = circularStack[--trueDepth];

                    if (parsedEntry.MsgNum == trueEntry.EntryLineNum)
                    {
                        // All the other ones will also match.
                        break;
                    }
                    else
                    {
                        MissingEntryRecords.Add(new Record(this, trueEntry));
                        MissingExitRecords.Add(new Record(parsedEntry));
                    }
                }

                NonCircularStack = null; // We're done.
            }
        }
Exemplo n.º 2
0
        // This constructs a missing MethodEntry Record from the given ReaderStackEntry.
        public Record(ReaderThreadInfo threadInfo, ReaderStackEntry methodEntry)
        {
            IsEntry    = true;
            MsgNum     = 0;                 // TBD
            Time       = DateTime.MinValue; // TBD
            Index      = 0;                 // TBD
            Thread     = threadInfo.Thread;
            ThreadName = threadInfo.ThreadName;
            Level      = methodEntry.Level;
            Logger     = methodEntry.Logger;
            StackDepth = methodEntry.Depth;
            MethodName = methodEntry.Method;
            Lines      = new string[] { string.Format("{{{0}: entered (replaces record lost due to wrapping)", MethodName) };

            // Each record also has a bool to indicate if it is bookmarked
            // and a row index it may map to.
            IsBookmarked = new bool[1];
            RowIndices   = new int[1];
        }
Exemplo n.º 3
0
        public Record ReadRecord()
        {
            // Read the DataFlags, then the data the Flags indicate is there.
            // Data must be read in the same order it was written (see FileLogging.WriteData).
            try {
                DataFlags flags = GetFlags();

                if (flags == DataFlags.None)
                {
                    return(null);
                }

                long startPos = _fileReader.BaseStream.Position;

                if ((flags & DataFlags.LineNumber) != DataFlags.None)
                {
                    _recordNumber = _fileReader.ReadUInt32();
                }
                else if (!InCircularPart)
                {
                    ++_recordNumber;
                }
                else
                {
                    // _recordNumber was incremented by GetFlags.
                }

                if ((flags & DataFlags.Time) != DataFlags.None)
                {
                    _time = new DateTime(_fileReader.ReadInt64());
                }

                if ((flags & DataFlags.ThreadId) != DataFlags.None)
                {
                    _threadId = _fileReader.ReadInt32();

                    // Look up or add the entry for this ThreadId.
                    if (!_foundThreadIds.TryGetValue(_threadId, out _curThread))
                    {
                        // First occurrence of this id.
                        _curThread = new ReaderThreadInfo();

                        if (!_oldThreadIds.TryGetValue(_threadId, out _curThread.Thread))
                        {
                            _curThread.Thread = new ThreadObject();
                        }

                        _curThread.Thread.Id = _threadId;
                        ThreadObject.AllThreads.Add(_curThread.Thread);
                        _foundThreadIds[_threadId] = _curThread;
                    }
                }

                if ((flags & DataFlags.ThreadName) != DataFlags.None)
                {
                    // A normal thread's name can only change from null to non-null.
                    // ThreadPool threads can alternate between null and non-null.
                    // If a thread's name changes from non-null to null, the logger
                    // writes string.Empty for the thread name.
                    string threadNameStr = _fileReader.ReadString();
                    if (threadNameStr == string.Empty)
                    {
                        _curThread.ThreadName = FindOrCreateThreadName("Thread " + _curThread.Thread.Id);
                    }
                    else
                    {
                        _curThread.ThreadName = FindOrCreateThreadName(threadNameStr);
                    }
                }
                else if (_curThread.ThreadName == null)
                {
                    _curThread.ThreadName = FindOrCreateThreadName("Thread " + _curThread.Thread.Id);
                }

                if ((flags & DataFlags.TraceLevel) != DataFlags.None)
                {
                    _curThread.Level = (TracerX.TraceLevel)_fileReader.ReadByte();
                    LevelsFound     |= _curThread.Level;
                }

                if (FormatVersion < 5)
                {
                    if ((flags & DataFlags.StackDepth) != DataFlags.None)
                    {
                        _curThread.Depth = _fileReader.ReadByte();
                    }
                    else if ((flags & DataFlags.MethodExit) != DataFlags.None)
                    {
                        --_curThread.Depth;
                    }
                }
                else
                {
                    if ((flags & DataFlags.StackDepth) != DataFlags.None)
                    {
                        _curThread.Depth = _fileReader.ReadByte();

                        if (InCircularPart)
                        {
                            if (_curThread.Depth > 0)
                            {
                                // In format version 5, we began logging each thread's current call
                                // stack on the thread's first line in each block (i.e. when the
                                // StackDepth flag is set). This is the thread's true call stack at
                                // this point in the log. It reflects MethodEntry and MethodExit
                                // records that may have been lost when the log wrapped (as well
                                // as those that weren't lost).

                                ReaderStackEntry[] trueStack = new ReaderStackEntry[_curThread.Depth];
                                for (int i = _curThread.Depth - 1; i >= 0; --i)
                                {
                                    ReaderStackEntry entry = new ReaderStackEntry();
                                    entry.EntryLineNum = _fileReader.ReadUInt32();
                                    entry.Level        = (TracerX.TraceLevel)_fileReader.ReadByte();
                                    entry.Logger       = GetLogger(_fileReader.ReadString());
                                    entry.Method       = _fileReader.ReadString();
                                    entry.Depth        = (byte)i;
                                    trueStack[i]       = entry;
                                }

                                _curThread.MakeMissingRecords(trueStack);
                            }
                            else
                            {
                                _curThread.MakeMissingRecords(null);
                            }
                        }
                    }

                    // Starting in format version 5, the viewer decrements the depth on MethodExit
                    // lines even if it was included on the line.
                    if ((flags & DataFlags.MethodExit) != DataFlags.None)
                    {
                        --_curThread.Depth;
                    }
                }

                if ((flags & DataFlags.LoggerName) != DataFlags.None)
                {
                    string loggerName = _fileReader.ReadString();
                    _curThread.Logger = GetLogger(loggerName);
                }

                if ((flags & DataFlags.MethodName) != DataFlags.None)
                {
                    _curThread.MethodName = _fileReader.ReadString();
                }

                if ((flags & DataFlags.Message) != DataFlags.None)
                {
                    _msg = _fileReader.ReadString();
                }

                // Construct the Record before incrementing depth.
                Record record = new Record(flags, _recordNumber, _time, _curThread, _msg);

                if ((flags & DataFlags.MethodEntry) != DataFlags.None)
                {
                    // Cause future records to be indented until a MethodExit is encountered.
                    ++_curThread.Depth;

                    // In format version 5+, we keep track of the call stack in the noncircular
                    // part of the log by "pushing" MethodEntry records and "popping" MethodExit records
                    if (FormatVersion >= 5 && !InCircularPart)
                    {
                        _curThread.Push(record);
                    }
                }
                else if (FormatVersion >= 5 && !InCircularPart && (flags & DataFlags.MethodExit) != DataFlags.None)
                {
                    _curThread.Pop();
                }

                BytesRead += _fileReader.BaseStream.Position - startPos;

                if (InCircularPart && _fileReader.BaseStream.Position >= MaxMb << 20)
                {
                    // We've read to the max file size in circular mode.  Wrap.
                    _fileReader.BaseStream.Position = _circularStartPos;
                }

                ++_recordsRead;
                return(record);
            } catch (Exception ex) {
                // The exception is either end-of-file or a corrupt file.
                // Either way, we're done.  Returning null tells the caller to give up.
                return(null);
            }
        }