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