//----------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. // //----------------------------------------------------------------------- namespace Microsoft.Isam.Esent.Interop.Windows10 { using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.InteropServices; /// /// Contains cumulative statistics on the work performed by the database /// engine on the current thread. This information is returned via /// JetGetThreadStats. /// [StructLayout(LayoutKind.Sequential)] [SuppressMessage( "Microsoft.StyleCop.CSharp.NamingRules", "SA1300:ElementMustBeginWithUpperCaseLetter", Justification = "This should match the unmanaged API, which isn't capitalized.")] [Serializable] [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "This should match the unmanaged API, which isn't capitalized.")] public struct JET_THREADSTATS2 : IEquatable { /// /// The size of a JET_THREADSTATS2 structure. /// internal static readonly int Size = Marshal.SizeOf(typeof(JET_THREADSTATS2)); /// /// Size of the structure. This is used for interop. /// private readonly int cbStruct; /// /// Number of pages visited. /// private int pagesReferenced; /// /// Number of pages read from disk. /// private int pagesRead; /// /// Number of pages preread. /// private int pagesPreread; /// /// Number of pages dirtied. /// private int pagesDirtied; /// /// Pages redirtied. /// private int pagesRedirtied; /// /// Number of log records generated. /// private int numLogRecords; /// /// Number of bytes logged. /// private int loggedBytes; /// /// Elapsed time for pages cache missed in microseconds. /// private long usecsCacheMisses; /// /// Number of pages cache missed. /// private int pagesCacheMisses; /// /// Gets the total number of database pages visited by the database /// engine on the current thread. /// public int cPageReferenced { [DebuggerStepThrough] get { return this.pagesReferenced; } internal set { this.pagesReferenced = value; } } /// /// Gets the total number of database pages fetched from disk by the /// database engine on the current thread. /// public int cPageRead { [DebuggerStepThrough] get { return this.pagesRead; } internal set { this.pagesRead = value; } } /// /// Gets the total number of database pages prefetched from disk by /// the database engine on the current thread. /// public int cPagePreread { [DebuggerStepThrough] get { return this.pagesPreread; } internal set { this.pagesPreread = value; } } /// /// Gets the total number of database pages, with no unwritten changes, /// that have been modified by the database engine on the current thread. /// public int cPageDirtied { [DebuggerStepThrough] get { return this.pagesDirtied; } internal set { this.pagesDirtied = value; } } /// /// Gets the total number of database pages, with unwritten changes, that /// have been modified by the database engine on the current thread. /// public int cPageRedirtied { [DebuggerStepThrough] get { return this.pagesRedirtied; } internal set { this.pagesRedirtied = value; } } /// /// Gets the total number of transaction log records that have been /// generated by the database engine on the current thread. /// public int cLogRecord { [DebuggerStepThrough] get { return this.numLogRecords; } internal set { this.numLogRecords = value; } } /// /// Gets the total size, in bytes, of transaction log records that /// have been generated by the database engine on the current thread. /// public int cbLogRecord { [DebuggerStepThrough] get { return this.loggedBytes; } internal set { this.loggedBytes = value; } } /// /// Gets the cumulative latency, in microseconds, of cache misses experienced by /// this thread. /// public long cusecPageCacheMiss { [DebuggerStepThrough] get { return this.usecsCacheMisses; } internal set { this.usecsCacheMisses = value; } } /// /// Gets the cumulative count of cache misses experienced by the thread. /// public int cPageCacheMiss { [DebuggerStepThrough] get { return this.pagesCacheMisses; } internal set { this.pagesCacheMisses = value; } } /// /// Create a new struct with the specified /// valued. /// /// /// Number of pages visited. /// /// /// Number of pages read. /// /// /// Number of pages preread. /// /// /// TNumber of pages dirtied. /// /// /// Number of pages redirtied. /// /// /// Number of log records generated. /// /// /// Bytes of log records written. /// /// /// Elapsed time for pages cache missed in microseconds. /// /// /// Number of pages cache missed. /// /// /// A new struct with the specified values. /// public static JET_THREADSTATS2 Create( int cPageReferenced, int cPageRead, int cPagePreread, int cPageDirtied, int cPageRedirtied, int cLogRecord, int cbLogRecord, long cusecPageCacheMiss, int cPageCacheMiss) { return new JET_THREADSTATS2 { cPageReferenced = cPageReferenced, cPageRead = cPageRead, cPagePreread = cPagePreread, cPageDirtied = cPageDirtied, cPageRedirtied = cPageRedirtied, cLogRecord = cLogRecord, cbLogRecord = cbLogRecord, cusecPageCacheMiss = cusecPageCacheMiss, cPageCacheMiss = cPageCacheMiss, }; } /// /// Add the stats in two JET_THREADSTATS2 structures. /// /// The first JET_THREADSTATS2. /// The second JET_THREADSTATS2. /// A JET_THREADSTATS2 containing the result of adding the stats in t1 and t2. public static JET_THREADSTATS2 Add(JET_THREADSTATS2 t1, JET_THREADSTATS2 t2) { unchecked { return new JET_THREADSTATS2 { cPageReferenced = t1.cPageReferenced + t2.cPageReferenced, cPageRead = t1.cPageRead + t2.cPageRead, cPagePreread = t1.cPagePreread + t2.cPagePreread, cPageDirtied = t1.cPageDirtied + t2.cPageDirtied, cPageRedirtied = t1.cPageRedirtied + t2.cPageRedirtied, cLogRecord = t1.cLogRecord + t2.cLogRecord, cbLogRecord = t1.cbLogRecord + t2.cbLogRecord, cusecPageCacheMiss = t1.cusecPageCacheMiss + t2.cusecPageCacheMiss, cPageCacheMiss = t1.cPageCacheMiss + t2.cPageCacheMiss, }; } } /// /// Add the stats in two JET_THREADSTATS2 structures. /// /// The first JET_THREADSTATS2. /// The second JET_THREADSTATS2. /// A JET_THREADSTATS2 containing the result of adding the stats in t1 and t2. public static JET_THREADSTATS2 operator +(JET_THREADSTATS2 t1, JET_THREADSTATS2 t2) { return Add(t1, t2); } /// /// Calculate the difference in stats between two JET_THREADSTATS2 structures. /// /// The first JET_THREADSTATS2. /// The second JET_THREADSTATS2. /// A JET_THREADSTATS2 containing the difference in stats between t1 and t2. public static JET_THREADSTATS2 Subtract(JET_THREADSTATS2 t1, JET_THREADSTATS2 t2) { unchecked { return new JET_THREADSTATS2 { cPageReferenced = t1.cPageReferenced - t2.cPageReferenced, cPageRead = t1.cPageRead - t2.cPageRead, cPagePreread = t1.cPagePreread - t2.cPagePreread, cPageDirtied = t1.cPageDirtied - t2.cPageDirtied, cPageRedirtied = t1.cPageRedirtied - t2.cPageRedirtied, cLogRecord = t1.cLogRecord - t2.cLogRecord, cbLogRecord = t1.cbLogRecord - t2.cbLogRecord, cusecPageCacheMiss = t1.cusecPageCacheMiss - t2.cusecPageCacheMiss, cPageCacheMiss = t1.cPageCacheMiss - t2.cPageCacheMiss, }; } } /// /// Calculate the difference in stats between two JET_THREADSTATS2 structures. /// /// The first JET_THREADSTATS2. /// The second JET_THREADSTATS2. /// A JET_THREADSTATS2 containing the difference in stats between t1 and t2. public static JET_THREADSTATS2 operator -(JET_THREADSTATS2 t1, JET_THREADSTATS2 t2) { return Subtract(t1, t2); } /// /// Determines whether two specified instances of JET_THREADSTATS2 /// are equal. /// /// The first instance to compare. /// The second instance to compare. /// True if the two instances are equal. public static bool operator ==(JET_THREADSTATS2 lhs, JET_THREADSTATS2 rhs) { return lhs.Equals(rhs); } /// /// Determines whether two specified instances of JET_THREADSTATS2 /// are not equal. /// /// The first instance to compare. /// The second instance to compare. /// True if the two instances are not equal. public static bool operator !=(JET_THREADSTATS2 lhs, JET_THREADSTATS2 rhs) { return !(lhs == rhs); } /// /// Gets a string representation of this object. /// /// A string representation of this object. public override string ToString() { // String.Concat is faster than using a StringBuilder. // use Int32.ToString instead of passing the Int32 to // String.Format (which requires boxing). return string.Concat( this.cPageReferenced.ToString("N0", CultureInfo.InvariantCulture), " page reference", GetPluralS(this.cPageReferenced), ", ", this.cPageRead.ToString("N0", CultureInfo.InvariantCulture), " page", GetPluralS(this.cPageRead), " read, ", this.cPagePreread.ToString("N0", CultureInfo.InvariantCulture), " page", GetPluralS(this.cPagePreread), " preread, ", this.cPageDirtied.ToString("N0", CultureInfo.InvariantCulture), " page", GetPluralS(this.cPageDirtied), " dirtied, ", this.cPageRedirtied.ToString("N0", CultureInfo.InvariantCulture), " page", GetPluralS(this.cPageRedirtied), " redirtied, ", this.cLogRecord.ToString("N0", CultureInfo.InvariantCulture), " log record", GetPluralS(this.cLogRecord), ", ", this.cbLogRecord.ToString("N0", CultureInfo.InvariantCulture), " byte", GetPluralS(this.cbLogRecord), " logged", ", ", this.cusecPageCacheMiss.ToString("N0", CultureInfo.InvariantCulture), " page cache miss latency (us)", ", ", this.cPageCacheMiss.ToString("N0", CultureInfo.InvariantCulture), " page cache miss count"); } /// /// Returns a value indicating whether this instance is equal /// to another instance. /// /// An object to compare with this instance. /// True if the two instances are equal. public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) { return false; } return this.Equals((JET_THREADSTATS2)obj); } /// /// Returns the hash code for this instance. /// /// The hash code for this instance. public override int GetHashCode() { return this.cPageReferenced ^ this.cPageRead << 1 ^ this.cPagePreread << 2 ^ this.cPageDirtied << 3 ^ this.cPageRedirtied << 4 ^ this.cLogRecord << 5 ^ this.cbLogRecord << 6 ^ this.cusecPageCacheMiss.GetHashCode() << 7 ^ this.cPageCacheMiss << 8; } /// /// Returns a value indicating whether this instance is equal /// to another instance. /// /// An instance to compare with this instance. /// True if the two instances are equal. public bool Equals(JET_THREADSTATS2 other) { return this.cPageCacheMiss == other.cPageCacheMiss && this.cusecPageCacheMiss == other.cusecPageCacheMiss && this.cbLogRecord == other.cbLogRecord && this.cLogRecord == other.cLogRecord && this.cPageDirtied == other.cPageDirtied && this.cPagePreread == other.cPagePreread && this.cPageRead == other.cPageRead && this.cPageRedirtied == other.cPageRedirtied && this.cPageReferenced == other.cPageReferenced; } /// /// Get the plural suffix ('s') for the given number. /// /// The number. /// The letter 's' if n is greater than 1. private static string GetPluralS(int n) { return n == 1 ? string.Empty : "s"; } } }