//----------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. // //----------------------------------------------------------------------- #if !MANAGEDESENT_ON_WSA // Not exposed in MSDK namespace Microsoft.Isam.Esent.Interop.Vista { using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using Microsoft.Isam.Esent.Interop.Vista; /// /// Used by to return information about a record's usage /// requirements in user data space, number of set columns, number of /// values, and ESENT record structure overhead space. /// [StructLayout(LayoutKind.Auto)] [SuppressMessage( "Microsoft.StyleCop.CSharp.NamingRules", "SA1300:ElementMustBeginWithUpperCaseLetter", Justification = "This should match the unmanaged API, which isn't capitalized.")] [Serializable] public struct JET_RECSIZE : IEquatable { /// /// User data in the record. /// private long userData; /// /// User data associated with the record, but in the LV tree. /// private long userLongValueData; /// /// Record overhead, including key size. /// private long overhead; /// /// Overhead of storing the long-value data. /// private long longValueOverhead; /// /// Number of fixed and variable columns. /// private long numNonTaggedColumns; /// /// Number of tagged columns in the record. /// private long numTaggedColumns; /// /// Number of extrinsic (separated) long values. /// private long numLongValues; /// /// Number of multi-values (itag > 1) in the record. /// private long numMultiValues; /// /// Number of compressed columns in the record. /// private long numCompressedColumns; /// /// Size of user data after being compressed. /// private long userDataAfterCompression; /// /// Size of the long value data after compression. /// private long userLongValueDataCompressed; /// /// Gets the user data set in the record. /// public long cbData { [DebuggerStepThrough] get { return this.userData; } internal set { this.userData = value; } } /// /// Gets the user data set in the record, but stored in the long-value tree. /// public long cbLongValueData { [DebuggerStepThrough] get { return this.userLongValueData; } internal set { this.userLongValueData = value; } } /// /// Gets the overhead of the ESENT record structure for this record. /// This includes the record's key size. /// public long cbOverhead { [DebuggerStepThrough] get { return this.overhead; } internal set { this.overhead = value; } } /// /// Gets the overhead of the long-value data. /// public long cbLongValueOverhead { [DebuggerStepThrough] get { return this.longValueOverhead; } internal set { this.longValueOverhead = value; } } /// /// Gets the total number of fixed and variable columns set in this record. /// public long cNonTaggedColumns { [DebuggerStepThrough] get { return this.numNonTaggedColumns; } internal set { this.numNonTaggedColumns = value; } } /// /// Gets the total number of tagged columns set in this record. /// public long cTaggedColumns { [DebuggerStepThrough] get { return this.numTaggedColumns; } internal set { this.numTaggedColumns = value; } } /// /// Gets the total number of long values stored in the long-value tree /// for this record. This does not include intrinsic long values. /// public long cLongValues { [DebuggerStepThrough] get { return this.numLongValues; } internal set { this.numLongValues = value; } } /// /// Gets the accumulation of the total number of values beyond the first /// for all columns in the record. /// public long cMultiValues { [DebuggerStepThrough] get { return this.numMultiValues; } internal set { this.numMultiValues = value; } } /// /// Gets the total number of columns in the record which are compressed. /// public long cCompressedColumns { [DebuggerStepThrough] get { return this.numCompressedColumns; } internal set { this.numCompressedColumns = value; } } /// /// Gets the compressed size of user data in record. This is the same /// as if no intrinsic long-values are compressed). /// public long cbDataCompressed { [DebuggerStepThrough] get { return this.userDataAfterCompression; } internal set { this.userDataAfterCompression = value; } } /// /// Gets the compressed size of user data in the long-value tree. This is /// the same as if no separated long values /// are compressed. /// public long cbLongValueDataCompressed { [DebuggerStepThrough] get { return this.userLongValueDataCompressed; } internal set { this.userLongValueDataCompressed = value; } } /// /// Add the sizes in two JET_RECSIZE structures. /// /// The first JET_RECSIZE. /// The second JET_RECSIZE. /// A JET_RECSIZE containing the result of adding the sizes in s1 and s2. public static JET_RECSIZE Add(JET_RECSIZE s1, JET_RECSIZE s2) { checked { return new JET_RECSIZE { cbData = s1.cbData + s2.cbData, cbDataCompressed = s1.cbDataCompressed + s2.cbDataCompressed, cbLongValueData = s1.cbLongValueData + s2.cbLongValueData, cbLongValueDataCompressed = s1.cbLongValueDataCompressed + s2.cbLongValueDataCompressed, cbLongValueOverhead = s1.cbLongValueOverhead + s2.cbLongValueOverhead, cbOverhead = s1.cbOverhead + s2.cbOverhead, cCompressedColumns = s1.cCompressedColumns + s2.cCompressedColumns, cLongValues = s1.cLongValues + s2.cLongValues, cMultiValues = s1.cMultiValues + s2.cMultiValues, cNonTaggedColumns = s1.cNonTaggedColumns + s2.cNonTaggedColumns, cTaggedColumns = s1.cTaggedColumns + s2.cTaggedColumns, }; } } /// /// Add the sizes in two JET_RECSIZE structures. /// /// The first JET_RECSIZE. /// The second JET_RECSIZE. /// A JET_RECSIZE containing the result of adding the sizes in left and right. public static JET_RECSIZE operator +(JET_RECSIZE left, JET_RECSIZE right) { return JET_RECSIZE.Add(left, right); } /// /// Calculate the difference in sizes between two JET_RECSIZE structures. /// /// The first JET_RECSIZE. /// The second JET_RECSIZE. /// A JET_RECSIZE containing the difference in sizes between s1 and s2. public static JET_RECSIZE Subtract(JET_RECSIZE s1, JET_RECSIZE s2) { checked { return new JET_RECSIZE { cbData = s1.cbData - s2.cbData, cbDataCompressed = s1.cbDataCompressed - s2.cbDataCompressed, cbLongValueData = s1.cbLongValueData - s2.cbLongValueData, cbLongValueDataCompressed = s1.cbLongValueDataCompressed - s2.cbLongValueDataCompressed, cbLongValueOverhead = s1.cbLongValueOverhead - s2.cbLongValueOverhead, cbOverhead = s1.cbOverhead - s2.cbOverhead, cCompressedColumns = s1.cCompressedColumns - s2.cCompressedColumns, cLongValues = s1.cLongValues - s2.cLongValues, cMultiValues = s1.cMultiValues - s2.cMultiValues, cNonTaggedColumns = s1.cNonTaggedColumns - s2.cNonTaggedColumns, cTaggedColumns = s1.cTaggedColumns - s2.cTaggedColumns, }; } } /// /// Calculate the difference in sizes between two JET_RECSIZE structures. /// /// The first JET_RECSIZE. /// The second JET_RECSIZE. /// A JET_RECSIZE containing the difference in sizes between left and right. public static JET_RECSIZE operator -(JET_RECSIZE left, JET_RECSIZE right) { return JET_RECSIZE.Subtract(left, right); } /// /// Determines whether two specified instances of JET_RECSIZE /// are equal. /// /// The first instance to compare. /// The second instance to compare. /// True if the two instances are equal. public static bool operator ==(JET_RECSIZE lhs, JET_RECSIZE rhs) { return lhs.Equals(rhs); } /// /// Determines whether two specified instances of JET_RECSIZE /// 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_RECSIZE lhs, JET_RECSIZE rhs) { return !(lhs == rhs); } /// /// 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 || this.GetType() != obj.GetType()) { return false; } return this.Equals((JET_RECSIZE)obj); } /// /// Returns the hash code for this instance. /// /// The hash code for this instance. public override int GetHashCode() { // Put the data count members first so they aren't // shifted as much. Column counts cannot get as high // so we don't worry about losing fidelity. long hash = this.cbData ^ this.cbDataCompressed << 1 ^ this.cbLongValueData << 2 ^ this.cbDataCompressed << 3 ^ this.cbLongValueDataCompressed << 4 ^ this.cbOverhead << 5 ^ this.cbLongValueOverhead << 6 ^ this.cNonTaggedColumns << 7 ^ this.cTaggedColumns << 8 ^ this.cLongValues << 9 ^ this.cMultiValues << 10 ^ this.cCompressedColumns << 11; return (int)(hash & 0xFFFFFFFF) ^ (int)(hash >> 32); } /// /// 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 bool Equals(JET_RECSIZE other) { return this.cbData == other.cbData && this.cbLongValueData == other.cbLongValueData && this.cbOverhead == other.cbOverhead && this.cbLongValueOverhead == other.cbLongValueOverhead && this.cNonTaggedColumns == other.cNonTaggedColumns && this.cTaggedColumns == other.cTaggedColumns && this.cLongValues == other.cLongValues && this.cMultiValues == other.cMultiValues && this.cCompressedColumns == other.cCompressedColumns && this.cbDataCompressed == other.cbDataCompressed && this.cbLongValueDataCompressed == other.cbLongValueDataCompressed; } /// /// Sets the fields of the object from a NATIVE_RECSIZE struct. /// /// /// The native recsize to set the values from. /// internal void SetFromNativeRecsize(NATIVE_RECSIZE value) { // This is used on versions of ESENT that don't support JetGetRecordSize2. // That means compression isn't supported so we can default the compression // members to 'non compressed' values. checked { this.cbData = (long)value.cbData; this.cbDataCompressed = (long)value.cbData; this.cbLongValueData = (long)value.cbLongValueData; this.cbLongValueDataCompressed = (long)value.cbLongValueData; this.cbLongValueOverhead = (long)value.cbLongValueOverhead; this.cbOverhead = (long)value.cbOverhead; this.cCompressedColumns = 0; this.cLongValues = (long)value.cLongValues; this.cMultiValues = (long)value.cMultiValues; this.cNonTaggedColumns = (long)value.cNonTaggedColumns; this.cTaggedColumns = (long)value.cTaggedColumns; } } /// /// Sets the fields of the object from a NATIVE_RECSIZE2 struct. /// /// /// The native recsize to set the values from. /// internal void SetFromNativeRecsize(NATIVE_RECSIZE2 value) { checked { this.cbData = (long)value.cbData; this.cbDataCompressed = (long)value.cbDataCompressed; this.cbLongValueData = (long)value.cbLongValueData; this.cbLongValueDataCompressed = (long)value.cbLongValueDataCompressed; this.cbLongValueOverhead = (long)value.cbLongValueOverhead; this.cbOverhead = (long)value.cbOverhead; this.cCompressedColumns = (long)value.cCompressedColumns; this.cLongValues = (long)value.cLongValues; this.cMultiValues = (long)value.cMultiValues; this.cNonTaggedColumns = (long)value.cNonTaggedColumns; this.cTaggedColumns = (long)value.cTaggedColumns; } } /// /// Gets a NATIVE_RECSIZE containing the values in this object. /// /// /// A NATIVE_RECSIZE initialized with the values in the object. /// internal NATIVE_RECSIZE GetNativeRecsize() { unchecked { return new NATIVE_RECSIZE { cbData = (ulong)this.cbData, cbLongValueData = (ulong)this.cbLongValueData, cbLongValueOverhead = (ulong)this.cbLongValueOverhead, cbOverhead = (ulong)this.cbOverhead, cLongValues = (ulong)this.cLongValues, cMultiValues = (ulong)this.cMultiValues, cNonTaggedColumns = (ulong)this.cNonTaggedColumns, cTaggedColumns = (ulong)this.cTaggedColumns, }; } } /// /// Gets a NATIVE_RECSIZE2 containing the values in this object. /// /// /// A NATIVE_RECSIZE2 initialized with the values in the object. /// internal NATIVE_RECSIZE2 GetNativeRecsize2() { unchecked { return new NATIVE_RECSIZE2 { cbData = (ulong)this.cbData, cbDataCompressed = (ulong)this.cbDataCompressed, cbLongValueData = (ulong)this.cbLongValueData, cbLongValueDataCompressed = (ulong)this.cbLongValueDataCompressed, cbLongValueOverhead = (ulong)this.cbLongValueOverhead, cbOverhead = (ulong)this.cbOverhead, cCompressedColumns = (ulong)this.cCompressedColumns, cLongValues = (ulong)this.cLongValues, cMultiValues = (ulong)this.cMultiValues, cNonTaggedColumns = (ulong)this.cNonTaggedColumns, cTaggedColumns = (ulong)this.cTaggedColumns, }; } } } /// /// The native version of the JET_RECSIZE structure. /// [StructLayout(LayoutKind.Sequential)] [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "This should match the unmanaged API, which isn't capitalized.")] [SuppressMessage( "Microsoft.StyleCop.CSharp.NamingRules", "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter", Justification = "This should match the unmanaged API, which isn't capitalized.")] internal struct NATIVE_RECSIZE { /// /// User data in record. /// public ulong cbData; /// /// User data associated with the record but stored in the long-value /// tree. Does NOT count intrinsic long-values. /// public ulong cbLongValueData; /// /// Record overhead. /// public ulong cbOverhead; /// /// Overhead of long-value data. Does not count intrinsic long-values. /// public ulong cbLongValueOverhead; /// /// Total number of fixed/variable columns. /// public ulong cNonTaggedColumns; /// /// Total number of tagged columns. /// public ulong cTaggedColumns; /// /// Total number of values stored in the long-value tree for this record. /// Does NOT count intrinsic long-values. /// public ulong cLongValues; /// /// Total number of values beyond the first for each column in the record. /// public ulong cMultiValues; } /// /// The native version of the JET_RECSIZE2 structure. /// [StructLayout(LayoutKind.Sequential)] [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "This should match the unmanaged API, which isn't capitalized.")] [SuppressMessage( "Microsoft.StyleCop.CSharp.NamingRules", "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter", Justification = "This should match the unmanaged API, which isn't capitalized.")] internal struct NATIVE_RECSIZE2 { /// /// User data in record. /// public ulong cbData; /// /// User data associated with the record but stored in the long-value /// tree. Does NOT count intrinsic long-values. /// public ulong cbLongValueData; /// /// Record overhead. /// public ulong cbOverhead; /// /// Overhead of long-value data. Does not count intrinsic long-values. /// public ulong cbLongValueOverhead; /// /// Total number of fixed/variable columns. /// public ulong cNonTaggedColumns; /// /// Total number of tagged columns. /// public ulong cTaggedColumns; /// /// Total number of values stored in the long-value tree for this record. /// Does NOT count intrinsic long-values. /// public ulong cLongValues; /// /// Total number of values beyond the first for each column in the record. /// public ulong cMultiValues; /// /// Total number of columns which are compressed. /// public ulong cCompressedColumns; /// /// Compressed size of user data in record. Same as cbData if no intrinsic /// long-values are compressed. /// public ulong cbDataCompressed; /// /// Compressed size of user data in the long-value tree. Same as /// cbLongValue data if no separated long values are compressed. /// public ulong cbLongValueDataCompressed; } } #endif // !MANAGEDESENT_ON_WSA