//-----------------------------------------------------------------------
// 
//     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";
        }
    }
}