//****************************************************************************************************** // LogStackTrace.cs - Gbtc // // Copyright © 2016, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/eclipse-1.0.php // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 10/24/2016 - Steven E. Chisholm // Generated original version of source code. // // //****************************************************************************************************** using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Diagnostics; using System.IO; using System.Text; using GSF.IO; namespace GSF.Diagnostics { /// /// Provides stack trace data that can be serialized to a stream. /// public class LogStackTrace : IEquatable { /// /// Gets the stack frame data /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] private readonly List m_frames; /// /// Gets the stack frame data /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public readonly ReadOnlyCollection Frames; /// /// Gets the hashcode for this class /// private readonly int m_hashCode; /// /// Creates the object /// private LogStackTrace() { m_frames = new List(); Frames = new ReadOnlyCollection(m_frames); } /// /// Creates a stack trace object /// /// gets if the file paths need to be looked up. /// the number of frames to skip. /// the maximum number of frames in the stack trace. public LogStackTrace(bool lookupFileInfo = true, int skipCount = 0, int maxStackFrames = int.MaxValue) { m_frames = new List(); Frames = new ReadOnlyCollection(m_frames); try { var trace = new StackTrace(skipCount + 1, lookupFileInfo); var frames = trace.GetFrames(); if (frames != null) { foreach (var frame in frames) { if (maxStackFrames <= 0) break; maxStackFrames--; m_frames.Add(new LogStackFrame(frame)); } } } catch (Exception) { //Sometimes a stack trace can not be obtained. Just silently ignore this error. } m_hashCode = ComputeHashCode(); } /// /// Loads stack trace information from the supplied /// /// where to load the stack trace information public LogStackTrace(Stream stream) { byte version = stream.ReadNextByte(); switch (version) { case 1: int count = stream.ReadInt32(); m_frames = new List(count); Frames = new ReadOnlyCollection(m_frames); while (count > 0) { count--; m_frames.Add(new LogStackFrame(stream)); } break; default: throw new VersionNotFoundException("Unknown StackTraceDetails Version"); } m_hashCode = ComputeHashCode(); } private int ComputeHashCode() { int code = Frames.Count; foreach (var frame in Frames) { code ^= frame.ComputeHashCode(); } return code; } /// /// Saves stack trace information to the supplied /// /// where to save the stack trace information public void Save(Stream stream) { stream.Write((byte)1); stream.Write(Frames.Count); foreach (var frame in Frames) { frame.Save(stream); } } /// /// Returns a string that represents the current object. /// /// /// A string that represents the current object. /// /// 2 public override string ToString() { if (Frames.Count == 0) return string.Empty; StringBuilder sb = new StringBuilder(); foreach (var frame in Frames) { sb.Append(" at "); frame.ToString(sb); sb.AppendLine(); } return sb.ToString(); } /// /// Serves as a hash function for a particular type. /// /// /// A hash code for the current . /// /// 2 public override int GetHashCode() { return (int)m_hashCode; } /// /// Determines whether the specified is equal to the current . /// /// /// true if the specified object is equal to the current object; otherwise, false. /// /// The object to compare with the current object. 2 public override bool Equals(object obj) { return Equals(obj as LogStackTrace); } /// /// Indicates whether the current object is equal to another object of the same type. /// /// /// true if the current object is equal to the parameter; otherwise, false. /// /// An object to compare with this object. public bool Equals(LogStackTrace other) { if (ReferenceEquals(this, other)) return true; if ((object)other == null || m_hashCode != other.m_hashCode || Frames.Count != other.Frames.Count) return false; for (int x = 0; x < Frames.Count; x++) { if (!Frames[x].Equals(other.Frames[x])) return false; } return true; } #region [ Static ] /// /// An empty stack trace. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly LogStackTrace Empty; static LogStackTrace() { Empty = new LogStackTrace(); } internal static void Initialize() { } #endregion } }