//******************************************************************************************************
// 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
}
}