//----------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. // //----------------------------------------------------------------------- namespace Microsoft.Isam.Esent.Interop { using System; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.InteropServices; /// /// The JET_SIGNATURE structure contains information that uniquely /// identifies a database or logfile sequence. /// [SuppressMessage( "Microsoft.StyleCop.CSharp.NamingRules", "SA1304:NonPrivateReadonlyFieldsMustBeginWithUpperCaseLetter", Justification = "This should match the name of the unmanaged structure.")] [SuppressMessage( "Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "This should match the name of the unmanaged structure.")] [SuppressMessage( "Microsoft.StyleCop.CSharp.NamingRules", "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter", Justification = "This should match the name of the unmanaged structure.")] [StructLayout(LayoutKind.Auto)] [Serializable] public struct JET_SIGNATURE : IEquatable { /// /// A randomly assigned number. /// internal readonly uint ulRandom; /// /// The time that the database or first logfile in the sequence was /// created. /// internal readonly JET_LOGTIME logtimeCreate; /// /// NetBIOS name of the computer. This may be null. /// private readonly string szComputerName; /// /// Initializes a new instance of the struct. /// /// The serialized representation of a JET_SIGNATURE from ToBytes(). public JET_SIGNATURE(byte[] bytes) { var nativeSignature = new NATIVE_SIGNATURE(); IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(nativeSignature)); Marshal.Copy(bytes, 0, ptr, Marshal.SizeOf(nativeSignature)); for (int i = bytes.Length; i < Marshal.SizeOf(nativeSignature); i++) { Marshal.WriteByte(ptr, i, 0); } nativeSignature = (NATIVE_SIGNATURE)Marshal.PtrToStructure(ptr, nativeSignature.GetType()); Marshal.FreeHGlobal(ptr); this.ulRandom = nativeSignature.ulRandom; this.logtimeCreate = nativeSignature.logtimeCreate; this.szComputerName = nativeSignature.szComputerName; } /// /// Initializes a new instance of the struct. /// /// A random number. /// The time for the creation time. /// The optional computer name. internal JET_SIGNATURE(int random, DateTime? time, string computerName) { this.ulRandom = unchecked((uint)random); this.logtimeCreate = time.HasValue ? new JET_LOGTIME(time.Value) : new JET_LOGTIME(); this.szComputerName = computerName; } /// /// Initializes a new instance of the struct. /// /// A native signature to initialize the members with. internal JET_SIGNATURE(NATIVE_SIGNATURE native) { this.ulRandom = native.ulRandom; this.logtimeCreate = native.logtimeCreate; this.szComputerName = native.szComputerName; } /// /// Determines whether two specified instances of JET_SIGNATURE /// are equal. /// /// The first instance to compare. /// The second instance to compare. /// True if the two instances are equal. public static bool operator ==(JET_SIGNATURE lhs, JET_SIGNATURE rhs) { return lhs.Equals(rhs); } /// /// Determines whether two specified instances of JET_SIGNATURE /// 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_SIGNATURE lhs, JET_SIGNATURE rhs) { return !(lhs == rhs); } /// /// Generate a string representation of the structure. /// /// The structure as a string. public override string ToString() { string convertedDate = string.Empty; DateTime? createDate = this.logtimeCreate.ToDateTime(); if (createDate.HasValue) { // the standard Round-trip date/time pattern convertedDate = createDate.Value.ToString("o", CultureInfo.InvariantCulture); } return string.Format( CultureInfo.InvariantCulture, "JET_SIGNATURE({0}:{1}:{2})", this.ulRandom, convertedDate, this.szComputerName); } /// /// Generate the serialized representation of the structure. /// /// The structure as a byte array. public byte[] ToBytes() { NATIVE_SIGNATURE nativeSignature = this.GetNativeSignature(); IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(nativeSignature)); Marshal.StructureToPtr(nativeSignature, ptr, false); byte[] bytes = new byte[Marshal.SizeOf(nativeSignature)]; Marshal.Copy(ptr, bytes, 0, Marshal.SizeOf(nativeSignature)); Marshal.FreeHGlobal(ptr); return bytes; } /// /// 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_SIGNATURE)obj); } /// /// Returns the hash code for this instance. /// /// The hash code for this instance. public override int GetHashCode() { return this.ulRandom.GetHashCode() ^ this.logtimeCreate.GetHashCode() ^ (null == this.szComputerName ? -1 : this.szComputerName.GetHashCode()); } /// /// 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_SIGNATURE other) { bool namesAreEqual = (string.IsNullOrEmpty(this.szComputerName) && string.IsNullOrEmpty(other.szComputerName)) || (!string.IsNullOrEmpty(this.szComputerName) && !string.IsNullOrEmpty(other.szComputerName) && this.szComputerName == other.szComputerName); return namesAreEqual && this.ulRandom == other.ulRandom && this.logtimeCreate == other.logtimeCreate; } /// /// Converts the structure to the native representation. /// /// The native representation of the signature. internal NATIVE_SIGNATURE GetNativeSignature() { var native = new NATIVE_SIGNATURE { ulRandom = this.ulRandom, szComputerName = this.szComputerName, logtimeCreate = this.logtimeCreate, }; return native; } } /// /// Native (interop) version of the JET_SIGNATURE structure. /// [SuppressMessage( "Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "This should match the name of the unmanaged structure.")] [SuppressMessage( "Microsoft.StyleCop.CSharp.NamingRules", "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter", Justification = "This should match the name of the unmanaged structure.")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] [Serializable] internal struct NATIVE_SIGNATURE { /// /// Size of the szComputerName array. /// public const int ComputerNameSize = 16; // JET_MAX_COMPUTER_NAME_LENGTH + 1 /// /// The size of a NATIVE_SIGNATURE structure. /// public static readonly int Size = Marshal.SizeOf(typeof(NATIVE_SIGNATURE)); /// /// A random number. /// public uint ulRandom; /// /// Time the database or log sequence was created. /// public JET_LOGTIME logtimeCreate; /// /// NetBIOS name of the computer. /// [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ComputerNameSize)] public string szComputerName; } }