mirror of
https://github.com/gnh1201/welsonjs.git
synced 2025-11-29 10:53:43 +00:00
Merge pull request #278 from gnh1201/dev
Introduce ESENT database to WelsonJS Launcher
This commit is contained in:
commit
c6f546778f
3033
WelsonJS.Toolkit/EsentInterop/Api.cs
Normal file
3033
WelsonJS.Toolkit/EsentInterop/Api.cs
Normal file
File diff suppressed because it is too large
Load Diff
64
WelsonJS.Toolkit/EsentInterop/ApiConstants.cs
Normal file
64
WelsonJS.Toolkit/EsentInterop/ApiConstants.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ApiConstants.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Constants for the ESENT API. These don't have to be looked up via
|
||||
/// system parameters.
|
||||
/// </summary>
|
||||
public static partial class SystemParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// The length of the prefix used to name files used by the database
|
||||
/// engine.
|
||||
/// </summary>
|
||||
public const int BaseNameLength = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum size of a table/column/index name.
|
||||
/// </summary>
|
||||
public const int NameMost = 64;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum size for columns which are not JET_coltyp.LongBinary
|
||||
/// or JET_coltyp.LongText.
|
||||
/// </summary>
|
||||
public const int ColumnMost = 255;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of columns allowed in a table.
|
||||
/// </summary>
|
||||
public const int ColumnsMost = 65248;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of fixed columns allowed in a table.
|
||||
/// </summary>
|
||||
public const int ColumnsFixedMost = 127;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of variable-length columns allowed
|
||||
/// in a table.
|
||||
/// </summary>
|
||||
public const int ColumnsVarMost = 128;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of tagged columns allowed in a table.
|
||||
/// </summary>
|
||||
public const int ColumnsTaggedMost = 64993;
|
||||
|
||||
/// <summary>
|
||||
/// The number of pages that gives the smallest possible
|
||||
/// temporary database.
|
||||
/// </summary>
|
||||
public const int PageTempDBSmallest = 14;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum length of a locale name (LOCALE_NAME_MAX_LENGTH from winnt.h).
|
||||
/// </summary>
|
||||
public const int LocaleNameMaxLength = 85;
|
||||
}
|
||||
}
|
||||
96
WelsonJS.Toolkit/EsentInterop/BoolColumnValue.cs
Normal file
96
WelsonJS.Toolkit/EsentInterop/BoolColumnValue.cs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="BoolColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="bool"/> column value.
|
||||
/// </summary>
|
||||
public class BoolColumnValue : ColumnValueOfStruct<bool>
|
||||
{
|
||||
/// <summary>
|
||||
/// A boxed true value that can be used by ValueAsObject.
|
||||
/// </summary>
|
||||
private static readonly object BoxedTrue = true;
|
||||
|
||||
/// <summary>
|
||||
/// A boxed false value that can be used by ValueAsObject.
|
||||
/// </summary>
|
||||
private static readonly object BoxedFalse = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last set or retrieved value of the column. The
|
||||
/// value is returned as a generic object.
|
||||
/// </summary>
|
||||
public override object ValueAsObject
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.Value.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.Value.Value ? BoxedTrue : BoxedFalse;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return sizeof(bool); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
byte data = this.Value.GetValueOrDefault() ? (byte)0xFF : (byte)0x00;
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(byte), this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
this.Value = BitConverter.ToBoolean(value, startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
WelsonJS.Toolkit/EsentInterop/BoxedValueCache.cs
Normal file
51
WelsonJS.Toolkit/EsentInterop/BoxedValueCache.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="BoxedValueCache.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// A cache for boxed values.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object to cache.</typeparam>
|
||||
internal static class BoxedValueCache<T> where T : struct, IEquatable<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of boxed values to cache.
|
||||
/// </summary>
|
||||
private const int NumCachedBoxedValues = 257;
|
||||
|
||||
/// <summary>
|
||||
/// Cached boxed values.
|
||||
/// </summary>
|
||||
private static readonly object[] BoxedValues = new object[NumCachedBoxedValues];
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boxed version of the value. A cached copy is used if possible.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to box.</param>
|
||||
/// <returns>A boxed version of the value.</returns>
|
||||
public static object GetBoxedValue(T? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
T valueToBox = value.Value;
|
||||
int index = (valueToBox.GetHashCode() & 0x7fffffff) % NumCachedBoxedValues;
|
||||
object boxedValue = BoxedValues[index];
|
||||
if (null == boxedValue || !((T)boxedValue).Equals(valueToBox))
|
||||
{
|
||||
boxedValue = valueToBox;
|
||||
BoxedValues[index] = boxedValue;
|
||||
}
|
||||
|
||||
return boxedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
68
WelsonJS.Toolkit/EsentInterop/ByteColumnValue.cs
Normal file
68
WelsonJS.Toolkit/EsentInterop/ByteColumnValue.cs
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ByteColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="byte"/> column value.
|
||||
/// </summary>
|
||||
public class ByteColumnValue : ColumnValueOfStruct<byte>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return sizeof(byte); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
var data = this.Value.GetValueOrDefault();
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(byte), this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
this.Value = value[startIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
136
WelsonJS.Toolkit/EsentInterop/BytesColumnValue.cs
Normal file
136
WelsonJS.Toolkit/EsentInterop/BytesColumnValue.cs
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="BytesColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A byte array column value.
|
||||
/// </summary>
|
||||
public class BytesColumnValue : ColumnValue
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal value.
|
||||
/// </summary>
|
||||
private byte[] internalValue;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last set or retrieved value of the column. The
|
||||
/// value is returned as a generic object.
|
||||
/// </summary>
|
||||
public override object ValueAsObject
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.Value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the column. Use <see cref="Api.SetColumns"/> to update a
|
||||
/// record with the column value.
|
||||
/// </summary>
|
||||
public byte[] Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.internalValue;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.internalValue = value;
|
||||
this.Error = value == null ? JET_wrn.ColumnNull : JET_wrn.Success;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte length of a column value, which is zero if column is null, otherwise
|
||||
/// matches the actual length of the byte array.
|
||||
/// </summary>
|
||||
public override int Length
|
||||
{
|
||||
get { return this.Value != null ? this.Value.Length : 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="BytesColumnValue"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="BytesColumnValue"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (null == this.Value)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return BitConverter.ToString(this.Value, 0, Math.Min(this.Value.Length, 16));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
if (null != this.Value)
|
||||
{
|
||||
fixed (void* buffer = this.Value)
|
||||
{
|
||||
return this.SetColumns(
|
||||
sesid, tableid, columnValues, nativeColumns, i, buffer, this.Value.Length, true);
|
||||
}
|
||||
}
|
||||
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, null, 0, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var copiedValue = new byte[count];
|
||||
Buffer.BlockCopy(value, startIndex, copiedValue, 0, count);
|
||||
this.Value = copiedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
WelsonJS.Toolkit/EsentInterop/Caches.cs
Normal file
79
WelsonJS.Toolkit/EsentInterop/Caches.cs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Caches.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// Static class containing MemoryCaches for different ESENT buffers.
|
||||
/// Use these to avoid memory allocations when the memory will be
|
||||
/// used for a brief time.
|
||||
/// </summary>
|
||||
internal static class Caches
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum key size that any version of ESENT can have for
|
||||
/// any page size. This is also the maximum bookmark size.
|
||||
/// </summary>
|
||||
private const int KeyMostMost = 2000;
|
||||
|
||||
/// <summary>
|
||||
/// Reserve 1 extra space for keys made with prefix or wildcard.
|
||||
/// </summary>
|
||||
private const int LimitKeyMostMost = KeyMostMost + 1;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of buffers we want in a cache.
|
||||
/// </summary>
|
||||
private const int MaxBuffers = 16;
|
||||
|
||||
/// <summary>
|
||||
/// Cached buffers for columns.
|
||||
/// </summary>
|
||||
private static readonly MemoryCache TheColumnCache = new MemoryCache(128 * 1024, MaxBuffers);
|
||||
|
||||
/// <summary>
|
||||
/// Cached buffers for keys and bookmarks.
|
||||
/// </summary>
|
||||
private static readonly MemoryCache TheBookmarkCache = new MemoryCache(LimitKeyMostMost, MaxBuffers);
|
||||
|
||||
/// <summary>
|
||||
/// Cached buffers for keys and bookmarks.
|
||||
/// </summary>
|
||||
private static readonly MemoryCache TheSecondaryBookmarkCache = new MemoryCache(LimitKeyMostMost, MaxBuffers);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cached buffers for columns.
|
||||
/// </summary>
|
||||
public static MemoryCache ColumnCache
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return TheColumnCache; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cached buffers for keys and bookmarks.
|
||||
/// </summary>
|
||||
public static MemoryCache BookmarkCache
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return TheBookmarkCache; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cached buffers for keys and secondary bookmarks.
|
||||
/// </summary>
|
||||
public static MemoryCache SecondaryBookmarkCache
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get
|
||||
{
|
||||
return TheSecondaryBookmarkCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
98
WelsonJS.Toolkit/EsentInterop/CallbackWrappers.cs
Normal file
98
WelsonJS.Toolkit/EsentInterop/CallbackWrappers.cs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="CallbackWrappers.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// A collection of wrapped callbacks. This is used when the wrapped callback
|
||||
/// can be garbage collected. The wrappers should be removed from the collection
|
||||
/// when the callback is collected.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Removing the wrappers can lead to crashes. In this case we trust
|
||||
/// the client code to keep its callback alive until ESENT doesn't need it any
|
||||
/// more. Once the wrapped callback is garbage collected we allow the wrapper
|
||||
/// to be collected as well. If ESENT subsequently uses the callback there will
|
||||
/// be a crash.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The reason this is hard to deal with is that the lifetime of a JET_CALLBACK
|
||||
/// isn't very clear. Table callbacks can stick around until the table meta-data
|
||||
/// is purged, while a JetDefragment callback can be used until defrag ends. On
|
||||
/// the other hand, keeping the callback wrapper alive indefinitely would lead
|
||||
/// to unbounded memory use.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
internal sealed class CallbackWrappers
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to synchronize access to this object.
|
||||
/// </summary>
|
||||
private readonly object lockObject = new object();
|
||||
|
||||
/// <summary>
|
||||
/// A list of the wrapped callbacks.
|
||||
/// </summary>
|
||||
private readonly List<JetCallbackWrapper> callbackWrappers = new List<JetCallbackWrapper>();
|
||||
|
||||
/// <summary>
|
||||
/// Wrap a callback and returns its wrapper. If the callback is
|
||||
/// already wrapped then the existing wrapper is returned.
|
||||
/// </summary>
|
||||
/// <param name="callback">The callback to add.</param>
|
||||
/// <returns>The callback wrapper for the callback.</returns>
|
||||
public JetCallbackWrapper Add(JET_CALLBACK callback)
|
||||
{
|
||||
lock (this.lockObject)
|
||||
{
|
||||
JetCallbackWrapper wrapper;
|
||||
if (!this.TryFindWrapperFor(callback, out wrapper))
|
||||
{
|
||||
wrapper = new JetCallbackWrapper(callback);
|
||||
this.callbackWrappers.Add(wrapper);
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Go through the collection of callback wrappers and remove any dead callbacks.
|
||||
/// </summary>
|
||||
public void Collect()
|
||||
{
|
||||
lock (this.lockObject)
|
||||
{
|
||||
this.callbackWrappers.RemoveAll(wrapper => !wrapper.IsAlive);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Look in the list of callback wrappers to see if there is already an entry for
|
||||
/// this callback.
|
||||
/// </summary>
|
||||
/// <param name="callback">The callback to look for.</param>
|
||||
/// <param name="wrapper">Returns the wrapper, if found.</param>
|
||||
/// <returns>True if a wrapper was found, false otherwise.</returns>
|
||||
private bool TryFindWrapperFor(JET_CALLBACK callback, out JetCallbackWrapper wrapper)
|
||||
{
|
||||
foreach (JetCallbackWrapper w in this.callbackWrappers)
|
||||
{
|
||||
if (w.IsWrapping(callback))
|
||||
{
|
||||
wrapper = w;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
wrapper = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
101
WelsonJS.Toolkit/EsentInterop/ColumnInfo.cs
Normal file
101
WelsonJS.Toolkit/EsentInterop/ColumnInfo.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ColumnInfo.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
/// <summary>
|
||||
/// Information about one Esent column. This is not an interop
|
||||
/// class, but is used by the meta-data helper methods.
|
||||
/// </summary>
|
||||
public sealed class ColumnInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The default value of the column.
|
||||
/// </summary>
|
||||
private readonly ReadOnlyCollection<byte> defaultValue;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ColumnInfo class.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the column.</param>
|
||||
/// <param name="columnid">ID of the column.</param>
|
||||
/// <param name="coltyp">Type of the column.</param>
|
||||
/// <param name="cp">Codepage of the column.</param>
|
||||
/// <param name="maxLength">Maximum length of the column.</param>
|
||||
/// <param name="defaultValue">Column default value.</param>
|
||||
/// <param name="grbit">Column option.</param>
|
||||
internal ColumnInfo(
|
||||
string name,
|
||||
JET_COLUMNID columnid,
|
||||
JET_coltyp coltyp,
|
||||
JET_CP cp,
|
||||
int maxLength,
|
||||
byte[] defaultValue,
|
||||
ColumndefGrbit grbit)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Columnid = columnid;
|
||||
this.Coltyp = coltyp;
|
||||
this.Cp = cp;
|
||||
this.MaxLength = maxLength;
|
||||
this.defaultValue = (null == defaultValue) ? null : new ReadOnlyCollection<byte>(defaultValue);
|
||||
this.Grbit = grbit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the column.
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ID of the column.
|
||||
/// </summary>
|
||||
public JET_COLUMNID Columnid { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the column.
|
||||
/// </summary>
|
||||
public JET_coltyp Coltyp { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the code page of the column.
|
||||
/// </summary>
|
||||
public JET_CP Cp { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum length of the column.
|
||||
/// </summary>
|
||||
public int MaxLength { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default value of the column.
|
||||
/// </summary>
|
||||
public IList<byte> DefaultValue
|
||||
{
|
||||
get { return this.defaultValue; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the column options.
|
||||
/// </summary>
|
||||
public ColumndefGrbit Grbit { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="ColumnInfo"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="ColumnInfo"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
78
WelsonJS.Toolkit/EsentInterop/ColumnInfoEnumerator.cs
Normal file
78
WelsonJS.Toolkit/EsentInterop/ColumnInfoEnumerator.cs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ColumnInfoEnumerator.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System.Text;
|
||||
using Microsoft.Isam.Esent.Interop.Implementation;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for enumerators that return ColumnInfo objects. Subclasses differ
|
||||
/// by how they open the table.
|
||||
/// </summary>
|
||||
internal abstract class ColumnInfoEnumerator : TableEnumerator<ColumnInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ColumnInfoEnumerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="sesid">
|
||||
/// The session to use.
|
||||
/// </param>
|
||||
protected ColumnInfoEnumerator(JET_SESID sesid) : base(sesid)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the columnlist used to retrieve data.
|
||||
/// </summary>
|
||||
protected JET_COLUMNLIST Columnlist { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entry the cursor is currently positioned on.
|
||||
/// </summary>
|
||||
/// <returns>The entry the cursor is currently positioned on.</returns>
|
||||
protected override ColumnInfo GetCurrent()
|
||||
{
|
||||
return GetColumnInfoFromColumnlist(this.Sesid, this.Columnlist);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a ColumnInfo object from the data in the current JET_COLUMNLIST entry.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="columnlist">The columnlist to take the data from.</param>
|
||||
/// <returns>A ColumnInfo object containing the information from that record.</returns>
|
||||
private static ColumnInfo GetColumnInfoFromColumnlist(JET_SESID sesid, JET_COLUMNLIST columnlist)
|
||||
{
|
||||
// As of Sep 2015, JetGetColumnInfoW is only called for Win8+. Even though Unicode should have
|
||||
// worked in Win7, it wasn't reliable until Win8.
|
||||
Encoding encodingOfTextColumns = EsentVersion.SupportsWindows8Features ? Encoding.Unicode : LibraryHelpers.EncodingASCII;
|
||||
|
||||
string name = Api.RetrieveColumnAsString(
|
||||
sesid,
|
||||
columnlist.tableid,
|
||||
columnlist.columnidcolumnname,
|
||||
encodingOfTextColumns,
|
||||
RetrieveColumnGrbit.None);
|
||||
name = StringCache.TryToIntern(name);
|
||||
var columnidValue = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcolumnid);
|
||||
var coltypValue = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcoltyp);
|
||||
uint codepageValue = (ushort)Api.RetrieveColumnAsUInt16(sesid, columnlist.tableid, columnlist.columnidCp);
|
||||
var maxLength = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcbMax);
|
||||
byte[] defaultValue = Api.RetrieveColumn(sesid, columnlist.tableid, columnlist.columnidDefault);
|
||||
var grbitValue = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidgrbit);
|
||||
|
||||
return new ColumnInfo(
|
||||
name,
|
||||
new JET_COLUMNID { Value = columnidValue },
|
||||
(JET_coltyp)coltypValue,
|
||||
(JET_CP)codepageValue,
|
||||
unchecked((int)maxLength),
|
||||
defaultValue,
|
||||
(ColumndefGrbit)grbitValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
357
WelsonJS.Toolkit/EsentInterop/ColumnStream.cs
Normal file
357
WelsonJS.Toolkit/EsentInterop/ColumnStream.cs
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ColumnStream.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
/// <summary>
|
||||
/// This class provides a streaming interface to a long-value column
|
||||
/// (i.e. a column of type <see cref="JET_coltyp.LongBinary"/> or
|
||||
/// <see cref="JET_coltyp.LongText"/>).
|
||||
/// </summary>
|
||||
[SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules",
|
||||
"SA1305:FieldNamesMustNotUseHungarianNotation",
|
||||
Justification = "This should match the unmanaged API, which isn't capitalized.")]
|
||||
public class ColumnStream : Stream
|
||||
{
|
||||
/// <summary>
|
||||
/// The size of the biggest long-value column ESENT supports.
|
||||
/// </summary>
|
||||
private const int MaxLongValueSize = 0x7fffffff;
|
||||
|
||||
/// <summary>
|
||||
/// Session to use.
|
||||
/// </summary>
|
||||
private readonly JET_SESID sesid;
|
||||
|
||||
/// <summary>
|
||||
/// Cursor to use.
|
||||
/// </summary>
|
||||
private readonly JET_TABLEID tableid;
|
||||
|
||||
/// <summary>
|
||||
/// Columnid to use.
|
||||
/// </summary>
|
||||
private readonly JET_COLUMNID columnid;
|
||||
|
||||
/// <summary>
|
||||
/// Current LV offset.
|
||||
/// </summary>
|
||||
private int ibLongValue;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ColumnStream class.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to use.</param>
|
||||
/// <param name="columnid">The columnid of the column to set/retrieve data from.</param>
|
||||
public ColumnStream(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid)
|
||||
{
|
||||
// In some cases we rely on Int32 arithmetic overflow checking to catch
|
||||
// errors, which assumes that a long-value can store Int32.MaxValue bytes.
|
||||
Debug.Assert(MaxLongValueSize == int.MaxValue, "Expected maximum long value size to be Int32.MaxValue");
|
||||
|
||||
this.sesid = sesid;
|
||||
this.tableid = tableid;
|
||||
this.columnid = columnid;
|
||||
this.Itag = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the itag of the column.
|
||||
/// </summary>
|
||||
public int Itag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the stream supports reading.
|
||||
/// </summary>
|
||||
public override bool CanRead
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the stream supports writing.
|
||||
/// </summary>
|
||||
public override bool CanWrite
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the stream supports seeking.
|
||||
/// </summary>
|
||||
public override bool CanSeek
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current position in the stream.
|
||||
/// </summary>
|
||||
public override long Position
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get
|
||||
{
|
||||
return this.ibLongValue;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > MaxLongValueSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("value", value, "A long-value offset has to be between 0 and 0x7fffffff bytes");
|
||||
}
|
||||
|
||||
this.ibLongValue = checked((int)value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current length of the stream.
|
||||
/// </summary>
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
int size;
|
||||
var retinfo = new JET_RETINFO { itagSequence = this.Itag, ibLongValue = 0 };
|
||||
Api.JetRetrieveColumn(this.sesid, this.tableid, this.columnid, null, 0, out size, RetrieveGrbit, retinfo);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the options that should be used with JetRetrieveColumn.
|
||||
/// </summary>
|
||||
private static RetrieveColumnGrbit RetrieveGrbit
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get
|
||||
{
|
||||
// Always use the RetrieveCopy options. This makes the ColumnStream work
|
||||
// well when setting a column. If we don't always use RetrieveCopy then
|
||||
// things like seeking from the end of a column might not work properly.
|
||||
return RetrieveColumnGrbit.RetrieveCopy;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="ColumnStream"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="ColumnStream"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "ColumnStream(0x{0:x}:{1})", this.columnid.Value, this.Itag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flush the stream.
|
||||
/// </summary>
|
||||
public override void Flush()
|
||||
{
|
||||
// nothing is required
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a sequence of bytes to the current stream and advances the current
|
||||
/// position within this stream by the number of bytes written.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to write from.</param>
|
||||
/// <param name="offset">The offset in the buffer to write.</param>
|
||||
/// <param name="count">The number of bytes to write.</param>
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
CheckBufferArguments(buffer, offset, count);
|
||||
|
||||
int length = checked((int)this.Length);
|
||||
JET_SETINFO setinfo;
|
||||
|
||||
int newIbLongValue = checked(this.ibLongValue + count);
|
||||
|
||||
// If our current position is beyond the end of the LV extend
|
||||
// the LV to the write point
|
||||
if (this.ibLongValue > length)
|
||||
{
|
||||
setinfo = new JET_SETINFO { itagSequence = this.Itag };
|
||||
Api.JetSetColumn(this.sesid, this.tableid, this.columnid, null, this.ibLongValue, SetColumnGrbit.SizeLV, setinfo);
|
||||
length = this.ibLongValue;
|
||||
}
|
||||
|
||||
SetColumnGrbit grbit;
|
||||
if (this.ibLongValue == length)
|
||||
{
|
||||
grbit = SetColumnGrbit.AppendLV;
|
||||
}
|
||||
else if (newIbLongValue >= length)
|
||||
{
|
||||
grbit = SetColumnGrbit.OverwriteLV | SetColumnGrbit.SizeLV;
|
||||
}
|
||||
else
|
||||
{
|
||||
grbit = SetColumnGrbit.OverwriteLV;
|
||||
}
|
||||
|
||||
setinfo = new JET_SETINFO { itagSequence = this.Itag, ibLongValue = this.ibLongValue };
|
||||
Api.JetSetColumn(this.sesid, this.tableid, this.columnid, buffer, count, offset, grbit, setinfo);
|
||||
|
||||
checked
|
||||
{
|
||||
this.ibLongValue += count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a sequence of bytes from the current stream and advances the
|
||||
/// position within the stream by the number of bytes read.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to read into.</param>
|
||||
/// <param name="offset">The offset in the buffer to read into.</param>
|
||||
/// <param name="count">The number of bytes to read.</param>
|
||||
/// <returns>The number of bytes read into the buffer.</returns>
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
CheckBufferArguments(buffer, offset, count);
|
||||
|
||||
if (this.ibLongValue >= this.Length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int length;
|
||||
var retinfo = new JET_RETINFO { itagSequence = this.Itag, ibLongValue = this.ibLongValue };
|
||||
Api.JetRetrieveColumn(this.sesid, this.tableid, this.columnid, buffer, count, offset, out length, RetrieveGrbit, retinfo);
|
||||
int bytesRead = Math.Min(length, count);
|
||||
|
||||
checked
|
||||
{
|
||||
this.ibLongValue += bytesRead;
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the length of the stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The desired length, in bytes.</param>
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
if (value > MaxLongValueSize || value < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("value", value, "A LongValueStream cannot be longer than 0x7FFFFFF or less than 0 bytes");
|
||||
}
|
||||
|
||||
if (value < this.Length && value > 0)
|
||||
{
|
||||
// BUG: Shrinking the column multiple times and then growing it can sometimes hit an unpleasant
|
||||
// ESENT defect which causes a hang. To make sure we never have that problem we read out the data,
|
||||
// and insert into a new long-value. This is not efficient.
|
||||
var data = new byte[value];
|
||||
var retinfo = new JET_RETINFO { itagSequence = this.Itag, ibLongValue = 0 };
|
||||
int actualDataSize;
|
||||
Api.JetRetrieveColumn(
|
||||
this.sesid,
|
||||
this.tableid,
|
||||
this.columnid,
|
||||
data,
|
||||
data.Length,
|
||||
out actualDataSize,
|
||||
RetrieveGrbit,
|
||||
retinfo);
|
||||
|
||||
var setinfo = new JET_SETINFO { itagSequence = this.Itag };
|
||||
Api.JetSetColumn(this.sesid, this.tableid, this.columnid, data, data.Length, SetColumnGrbit.None, setinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
var setinfo = new JET_SETINFO { itagSequence = this.Itag };
|
||||
SetColumnGrbit grbit = (0 == value) ? SetColumnGrbit.ZeroLength : SetColumnGrbit.SizeLV;
|
||||
Api.JetSetColumn(this.sesid, this.tableid, this.columnid, null, checked((int)value), grbit, setinfo);
|
||||
}
|
||||
|
||||
// Setting the length moves the offset back to the end of the data
|
||||
if (this.ibLongValue > value)
|
||||
{
|
||||
this.ibLongValue = checked((int)value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the position in the current stream.
|
||||
/// </summary>
|
||||
/// <param name="offset">Byte offset relative to the origin parameter.</param>
|
||||
/// <param name="origin">A SeekOrigin indicating the reference point for the new position.</param>
|
||||
/// <returns>The new position in the current stream.</returns>
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
long newOffset;
|
||||
switch (origin)
|
||||
{
|
||||
case SeekOrigin.Begin:
|
||||
newOffset = offset;
|
||||
break;
|
||||
case SeekOrigin.End:
|
||||
newOffset = checked(this.Length + offset);
|
||||
break;
|
||||
case SeekOrigin.Current:
|
||||
newOffset = checked(this.ibLongValue + offset);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("origin", origin, "Unknown origin");
|
||||
}
|
||||
|
||||
if (newOffset < 0 || newOffset > MaxLongValueSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("offset", offset, "invalid offset/origin combination");
|
||||
}
|
||||
|
||||
this.ibLongValue = checked((int)newOffset);
|
||||
return this.ibLongValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check the buffer arguments given to Read/Write .
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer.</param>
|
||||
/// <param name="offset">The offset in the buffer to read/write to.</param>
|
||||
/// <param name="count">The number of bytes to read/write.</param>
|
||||
private static void CheckBufferArguments(ICollection<byte> buffer, int offset, int count)
|
||||
{
|
||||
if (null == buffer)
|
||||
{
|
||||
throw new ArgumentNullException("buffer");
|
||||
}
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("offset", offset, "cannot be negative");
|
||||
}
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("count", count, "cannot be negative");
|
||||
}
|
||||
|
||||
if (checked(buffer.Count - offset) < count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("count", count, "cannot be larger than the size of the buffer");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
382
WelsonJS.Toolkit/EsentInterop/ColumnValue.cs
Normal file
382
WelsonJS.Toolkit/EsentInterop/ColumnValue.cs
Normal file
|
|
@ -0,0 +1,382 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for objects that represent a column value to be set.
|
||||
/// </summary>
|
||||
public abstract partial class ColumnValue
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal grbit.
|
||||
/// </summary>
|
||||
private RetrieveColumnGrbit grbit;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ColumnValue class.
|
||||
/// </summary>
|
||||
protected ColumnValue()
|
||||
{
|
||||
this.ItagSequence = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the columnid to be set or retrieved.
|
||||
/// </summary>
|
||||
public JET_COLUMNID Columnid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last set or retrieved value of the column. The
|
||||
/// value is returned as a generic object.
|
||||
/// </summary>
|
||||
public abstract object ValueAsObject { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets column update options.
|
||||
/// </summary>
|
||||
public SetColumnGrbit SetGrbit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets column retrieval options.
|
||||
/// </summary>
|
||||
public RetrieveColumnGrbit RetrieveGrbit
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.grbit;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.ValidateRetrieveGrbit(value);
|
||||
this.grbit = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column itag sequence.
|
||||
/// </summary>
|
||||
public int ItagSequence { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the warning generated by retrieving or setting this column.
|
||||
/// </summary>
|
||||
public JET_wrn Error { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte length of a column value, which is zero if column is null, otherwise
|
||||
/// it matches the Size for fixed-size columns and represent the actual value byte
|
||||
/// length for variable sized columns (i.e. binary and string). For strings the length
|
||||
/// is determined in assumption two bytes per character.
|
||||
/// </summary>
|
||||
public abstract int Length { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected abstract int Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="ColumnValue"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="ColumnValue"/>.
|
||||
/// </returns>
|
||||
public abstract override string ToString();
|
||||
|
||||
/// <summary>
|
||||
/// Recursive RetrieveColumns method for data pinning. This should pin a buffer and
|
||||
/// call the inherited RetrieveColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to retrieve the columns from.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to retrieve.
|
||||
/// </param>
|
||||
internal static void RetrieveColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues)
|
||||
{
|
||||
const int MaxColumnValues = 1024;
|
||||
if (columnValues.Length > MaxColumnValues)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("columnValues", columnValues.Length, "Too many column values");
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte[] buffer = null;
|
||||
NATIVE_RETRIEVECOLUMN* nativeRetrievecolumns = stackalloc NATIVE_RETRIEVECOLUMN[columnValues.Length];
|
||||
|
||||
try
|
||||
{
|
||||
buffer = Caches.ColumnCache.Allocate();
|
||||
Debug.Assert(MaxColumnValues * 16 < buffer.Length, "Maximum size of fixed columns could exceed buffer size");
|
||||
|
||||
fixed (byte* pinnedBuffer = buffer)
|
||||
{
|
||||
byte* currentBuffer = pinnedBuffer;
|
||||
int numVariableLengthColumns = columnValues.Length;
|
||||
|
||||
// First the fixed-size columns
|
||||
for (int i = 0; i < columnValues.Length; ++i)
|
||||
{
|
||||
if (0 != columnValues[i].Size)
|
||||
{
|
||||
columnValues[i].MakeNativeRetrieveColumn(ref nativeRetrievecolumns[i]);
|
||||
nativeRetrievecolumns[i].pvData = new IntPtr(currentBuffer);
|
||||
nativeRetrievecolumns[i].cbData = checked((uint)columnValues[i].Size);
|
||||
|
||||
currentBuffer += nativeRetrievecolumns[i].cbData;
|
||||
Debug.Assert(currentBuffer <= pinnedBuffer + buffer.Length, "Moved past end of pinned buffer");
|
||||
|
||||
numVariableLengthColumns--;
|
||||
}
|
||||
}
|
||||
|
||||
// Now the variable-length columns
|
||||
if (numVariableLengthColumns > 0)
|
||||
{
|
||||
int bufferUsed = checked((int)(currentBuffer - pinnedBuffer));
|
||||
int bufferRemaining = checked(buffer.Length - bufferUsed);
|
||||
int bufferPerColumn = bufferRemaining / numVariableLengthColumns;
|
||||
Debug.Assert(bufferPerColumn > 0, "Not enough buffer left to retrieve variable length columns");
|
||||
|
||||
// Now the variable-size columns
|
||||
for (int i = 0; i < columnValues.Length; ++i)
|
||||
{
|
||||
if (0 == columnValues[i].Size)
|
||||
{
|
||||
columnValues[i].MakeNativeRetrieveColumn(ref nativeRetrievecolumns[i]);
|
||||
nativeRetrievecolumns[i].pvData = new IntPtr(currentBuffer);
|
||||
nativeRetrievecolumns[i].cbData = checked((uint)bufferPerColumn);
|
||||
currentBuffer += nativeRetrievecolumns[i].cbData;
|
||||
Debug.Assert(currentBuffer <= pinnedBuffer + buffer.Length, "Moved past end of pinned buffer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the columns
|
||||
Api.Check(Api.Impl.JetRetrieveColumns(sesid, tableid, nativeRetrievecolumns, columnValues.Length));
|
||||
|
||||
// Propagate the warnings and output.
|
||||
for (int i = 0; i < columnValues.Length; ++i)
|
||||
{
|
||||
columnValues[i].Error = (JET_wrn)nativeRetrievecolumns[i].err;
|
||||
columnValues[i].ItagSequence = (int)nativeRetrievecolumns[i].itagSequence;
|
||||
}
|
||||
|
||||
// Now parse out the columns that were retrieved successfully
|
||||
for (int i = 0; i < columnValues.Length; ++i)
|
||||
{
|
||||
if (nativeRetrievecolumns[i].err != (int)JET_wrn.BufferTruncated)
|
||||
{
|
||||
byte* columnBuffer = (byte*)nativeRetrievecolumns[i].pvData;
|
||||
int startIndex = checked((int)(columnBuffer - pinnedBuffer));
|
||||
columnValues[i].GetValueFromBytes(
|
||||
buffer,
|
||||
startIndex,
|
||||
checked((int)nativeRetrievecolumns[i].cbActual),
|
||||
nativeRetrievecolumns[i].err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally retrieve the buffers where the columns weren't large enough.
|
||||
RetrieveTruncatedBuffers(sesid, tableid, columnValues, nativeRetrievecolumns);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
Caches.ColumnCache.Free(ref buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This should populate the buffer and
|
||||
/// call the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal abstract unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i);
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns function used to pin data.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <param name="buffer">The buffer for this object.</param>
|
||||
/// <param name="bufferSize">Size of the buffer for ths object.</param>
|
||||
/// <param name="hasValue">True if this object is non null.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
/// <remarks>
|
||||
/// This is marked as internal because it uses the NATIVE_SETCOLUMN type
|
||||
/// which is also marked as internal. It should be treated as a protected
|
||||
/// method though.
|
||||
/// </remarks>
|
||||
internal unsafe int SetColumns(
|
||||
JET_SESID sesid,
|
||||
JET_TABLEID tableid,
|
||||
ColumnValue[] columnValues,
|
||||
NATIVE_SETCOLUMN* nativeColumns,
|
||||
int i,
|
||||
void* buffer,
|
||||
int bufferSize,
|
||||
bool hasValue)
|
||||
{
|
||||
Debug.Assert(this == columnValues[i], "SetColumns should be called on the current object");
|
||||
this.MakeNativeSetColumn(ref nativeColumns[i]);
|
||||
|
||||
if (hasValue)
|
||||
{
|
||||
nativeColumns[i].cbData = checked((uint)bufferSize);
|
||||
nativeColumns[i].pvData = new IntPtr(buffer);
|
||||
if (0 == bufferSize)
|
||||
{
|
||||
nativeColumns[i].grbit |= (uint)SetColumnGrbit.ZeroLength;
|
||||
}
|
||||
}
|
||||
|
||||
int err = i == columnValues.Length - 1
|
||||
? Api.Impl.JetSetColumns(sesid, tableid, nativeColumns, columnValues.Length)
|
||||
: columnValues[i + 1].SetColumns(sesid, tableid, columnValues, nativeColumns, i + 1);
|
||||
|
||||
this.Error = (JET_wrn)nativeColumns[i].err;
|
||||
return err;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected abstract void GetValueFromBytes(byte[] value, int startIndex, int count, int err);
|
||||
|
||||
/// <summary>
|
||||
/// Validation for the requested retrieve options for the column.
|
||||
/// </summary>
|
||||
/// <param name="grbit">The retrieve options to validate.</param>
|
||||
protected virtual void ValidateRetrieveGrbit(RetrieveColumnGrbit grbit)
|
||||
{
|
||||
// We cannot support this request when there is no way to indicate that a column reference is returned.
|
||||
if ((grbit & (RetrieveColumnGrbit)0x00020000) != 0) // UnpublishedGrbits.RetrieveAsRefIfNotInRecord
|
||||
{
|
||||
throw new EsentInvalidGrbitException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the value for columns whose buffers were truncated.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The table to use.</param>
|
||||
/// <param name="columnValues">The column values.</param>
|
||||
/// <param name="nativeRetrievecolumns">
|
||||
/// The native retrieve columns that match the column values.
|
||||
/// </param>
|
||||
private static unsafe void RetrieveTruncatedBuffers(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_RETRIEVECOLUMN* nativeRetrievecolumns)
|
||||
{
|
||||
for (int i = 0; i < columnValues.Length; ++i)
|
||||
{
|
||||
if (nativeRetrievecolumns[i].err == (int)JET_wrn.BufferTruncated)
|
||||
{
|
||||
var buffer = new byte[nativeRetrievecolumns[i].cbActual];
|
||||
int actualSize;
|
||||
int err;
|
||||
var retinfo = new JET_RETINFO { itagSequence = columnValues[i].ItagSequence };
|
||||
|
||||
// Pin the buffer and retrieve the data
|
||||
fixed (byte* pinnedBuffer = buffer)
|
||||
{
|
||||
err = Api.Impl.JetRetrieveColumn(
|
||||
sesid,
|
||||
tableid,
|
||||
columnValues[i].Columnid,
|
||||
new IntPtr(pinnedBuffer),
|
||||
buffer.Length,
|
||||
out actualSize,
|
||||
columnValues[i].RetrieveGrbit,
|
||||
retinfo);
|
||||
}
|
||||
|
||||
if (JET_wrn.BufferTruncated == (JET_wrn)err)
|
||||
{
|
||||
string error = string.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
"Column size changed from {0} to {1}. The record was probably updated by another thread.",
|
||||
buffer.Length,
|
||||
actualSize);
|
||||
Trace.TraceError(error);
|
||||
throw new InvalidOperationException(error);
|
||||
}
|
||||
|
||||
// Throw errors, but put warnings in the structure
|
||||
Api.Check(err);
|
||||
columnValues[i].Error = (JET_wrn)err;
|
||||
|
||||
// For BytesColumnValue this will copy the data to a new array.
|
||||
// If this situation becomes common we should simply use the array.
|
||||
columnValues[i].GetValueFromBytes(buffer, 0, actualSize, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a native SetColumn from this object.
|
||||
/// </summary>
|
||||
/// <param name="setcolumn">The native setcolumn structure to fill in.</param>
|
||||
private void MakeNativeSetColumn(ref NATIVE_SETCOLUMN setcolumn)
|
||||
{
|
||||
setcolumn.columnid = this.Columnid.Value;
|
||||
setcolumn.grbit = (uint)this.SetGrbit;
|
||||
setcolumn.itagSequence = checked((uint)this.ItagSequence);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a native RetrieveColumn from this object.
|
||||
/// </summary>
|
||||
/// <param name="retrievecolumn">
|
||||
/// The retrieve column structure to fill in.
|
||||
/// </param>
|
||||
private void MakeNativeRetrieveColumn(ref NATIVE_RETRIEVECOLUMN retrievecolumn)
|
||||
{
|
||||
retrievecolumn.columnid = this.Columnid.Value;
|
||||
retrievecolumn.grbit = (uint)this.RetrieveGrbit;
|
||||
retrievecolumn.itagSequence = checked((uint)this.ItagSequence);
|
||||
}
|
||||
}
|
||||
}
|
||||
82
WelsonJS.Toolkit/EsentInterop/ColumnValueOfStruct.cs
Normal file
82
WelsonJS.Toolkit/EsentInterop/ColumnValueOfStruct.cs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ColumnValueOfStruct.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Set a column of a struct type (e.g. <see cref="Int32"/>/<see cref="Guid"/>).
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type to set.</typeparam>
|
||||
public abstract class ColumnValueOfStruct<T> : ColumnValue where T : struct, IEquatable<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal value.
|
||||
/// </summary>
|
||||
private T? internalValue;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last set or retrieved value of the column. The
|
||||
/// value is returned as a generic object.
|
||||
/// </summary>
|
||||
public override object ValueAsObject
|
||||
{
|
||||
get
|
||||
{
|
||||
return BoxedValueCache<T>.GetBoxedValue(this.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value in the struct.
|
||||
/// </summary>
|
||||
public T? Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.internalValue;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.internalValue = value;
|
||||
this.Error = value == null ? JET_wrn.ColumnNull : JET_wrn.Success;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte length of a column value, which is zero if column is null, otherwise
|
||||
/// it matches the Size for this fixed-size column.
|
||||
/// </summary>
|
||||
public override int Length
|
||||
{
|
||||
get { return this.Value.HasValue ? this.Size : 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a string representation of this object.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Value.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the retrieved data is exactly the size needed for
|
||||
/// the structure. An exception is thrown if there is a mismatch.
|
||||
/// </summary>
|
||||
/// <param name="count">The size of the retrieved data.</param>
|
||||
protected void CheckDataCount(int count)
|
||||
{
|
||||
if (this.Size != count)
|
||||
{
|
||||
throw new EsentInvalidColumnException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
175
WelsonJS.Toolkit/EsentInterop/Conversions.cs
Normal file
175
WelsonJS.Toolkit/EsentInterop/Conversions.cs
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Conversions.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
/// <summary>
|
||||
/// Provide methods to convert data and flags between
|
||||
/// Win32 and the .NET Framework.
|
||||
/// </summary>
|
||||
public static class Conversions
|
||||
{
|
||||
/// <summary>
|
||||
/// Maps a CompareOption enumeration to the corresponding LCMapString flag.
|
||||
/// </summary>
|
||||
private static readonly IDictionary<CompareOptions, uint> CompareOptionsToLcmapFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Maps an LCMapString flag to the corresponding CompareOption enumeration.
|
||||
/// </summary>
|
||||
private static readonly IDictionary<uint, CompareOptions> LcmapFlagsToCompareOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes static members of the Conversions class. This sets up the
|
||||
/// conversion mapping dictionaries.
|
||||
/// </summary>
|
||||
static Conversions()
|
||||
{
|
||||
// Rather than creating both dictionaries, define one as the inverse of the other.
|
||||
CompareOptionsToLcmapFlags = new Dictionary<CompareOptions, uint>
|
||||
{
|
||||
{ CompareOptions.IgnoreCase, NativeMethods.NORM_IGNORECASE },
|
||||
{ CompareOptions.IgnoreKanaType, NativeMethods.NORM_IGNOREKANATYPE },
|
||||
{ CompareOptions.IgnoreNonSpace, NativeMethods.NORM_IGNORENONSPACE },
|
||||
{ CompareOptions.IgnoreSymbols, NativeMethods.NORM_IGNORESYMBOLS },
|
||||
{ CompareOptions.IgnoreWidth, NativeMethods.NORM_IGNOREWIDTH },
|
||||
{ CompareOptions.StringSort, NativeMethods.SORT_STRINGSORT }
|
||||
};
|
||||
|
||||
LcmapFlagsToCompareOptions = InvertDictionary(CompareOptionsToLcmapFlags);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a double (OA date time format) to a DateTime. Unlike DateTime.FromOADate
|
||||
/// this doesn't throw exceptions.
|
||||
/// </summary>
|
||||
/// <param name="d">The double value.</param>
|
||||
/// <returns>A DateTime.</returns>
|
||||
public static DateTime ConvertDoubleToDateTime(double d)
|
||||
{
|
||||
try
|
||||
{
|
||||
return LibraryHelpers.FromOADate(d);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// Not all double values are valid OADates. We deal with out-of-range values
|
||||
// by returning either min or max
|
||||
return d < 0 ? DateTime.MinValue : DateTime.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given flags for LCMapFlags, turn them into compare options. Unknown options
|
||||
/// are ignored.
|
||||
/// </summary>
|
||||
/// <param name="lcmapFlags">LCMapString flags.</param>
|
||||
/// <returns>CompareOptions describing the (known) flags.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static CompareOptions CompareOptionsFromLCMapFlags(uint lcmapFlags)
|
||||
{
|
||||
// This should be a template, but there isn't an elegant way to express than with C# generics
|
||||
CompareOptions options = CompareOptions.None;
|
||||
foreach (uint flag in LcmapFlagsToCompareOptions.Keys)
|
||||
{
|
||||
if (flag == (lcmapFlags & flag))
|
||||
{
|
||||
options |= LcmapFlagsToCompareOptions[flag];
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Give CompareOptions, turn them into flags from LCMapString. Unknown options are ignored.
|
||||
/// </summary>
|
||||
/// <param name="compareOptions">The options to convert.</param>
|
||||
/// <returns>The LCMapString flags that match the compare options. Unsupported options are ignored.</returns>
|
||||
[CLSCompliant(false)]
|
||||
public static uint LCMapFlagsFromCompareOptions(CompareOptions compareOptions)
|
||||
{
|
||||
// This should be a template, but there isn't an elegant way to express than with C# generics
|
||||
uint flags = 0;
|
||||
foreach (CompareOptions option in CompareOptionsToLcmapFlags.Keys)
|
||||
{
|
||||
if (option == (compareOptions & option))
|
||||
{
|
||||
flags |= CompareOptionsToLcmapFlags[option];
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a Key=>Value dictionary create an inverted dictionary that maps Value=>Key.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The new value type (the key of the current dictionary).</typeparam>
|
||||
/// <typeparam name="TKey">The new key type (the value if the current dictionary).</typeparam>
|
||||
/// <param name="dict">The dictionary to invert.</param>
|
||||
/// <returns>An inverted dictionary.</returns>
|
||||
private static IDictionary<TKey, TValue> InvertDictionary<TValue, TKey>(ICollection<KeyValuePair<TValue, TKey>> dict)
|
||||
{
|
||||
var invertedDict = new Dictionary<TKey, TValue>(dict.Count);
|
||||
foreach (KeyValuePair<TValue, TKey> entry in dict)
|
||||
{
|
||||
invertedDict.Add(entry.Value, entry.Key);
|
||||
}
|
||||
|
||||
return invertedDict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class contains the unmanaged constants used in the conversion.
|
||||
/// </summary>
|
||||
internal static class NativeMethods
|
||||
{
|
||||
#region Win32 Constants
|
||||
|
||||
/// <summary>
|
||||
/// Ignore case.
|
||||
/// </summary>
|
||||
public const uint NORM_IGNORECASE = 0x00000001;
|
||||
|
||||
/// <summary>
|
||||
/// Ignore nonspacing chars.
|
||||
/// </summary>
|
||||
public const uint NORM_IGNORENONSPACE = 0x00000002;
|
||||
|
||||
/// <summary>
|
||||
/// Ignore symbols.
|
||||
/// </summary>
|
||||
public const uint NORM_IGNORESYMBOLS = 0x00000004;
|
||||
|
||||
/// <summary>
|
||||
/// Ignore kanatype.
|
||||
/// </summary>
|
||||
public const uint NORM_IGNOREKANATYPE = 0x00010000;
|
||||
|
||||
/// <summary>
|
||||
/// Ignore width.
|
||||
/// </summary>
|
||||
public const uint NORM_IGNOREWIDTH = 0x00020000;
|
||||
|
||||
/// <summary>
|
||||
/// Treat punctuation the same as symbols.
|
||||
/// </summary>
|
||||
public const uint SORT_STRINGSORT = 0x00001000;
|
||||
|
||||
/// <summary>
|
||||
/// Produce a normalized wide-character sort key.
|
||||
/// </summary>
|
||||
public const uint LCMAP_SORTKEY = 0x00000400;
|
||||
|
||||
#endregion Win32 Constants
|
||||
}
|
||||
}
|
||||
}
|
||||
70
WelsonJS.Toolkit/EsentInterop/DateTimeColumnValue.cs
Normal file
70
WelsonJS.Toolkit/EsentInterop/DateTimeColumnValue.cs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="DateTimeColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Guid"/> column value.
|
||||
/// </summary>
|
||||
public class DateTimeColumnValue : ColumnValueOfStruct<DateTime>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return sizeof(double); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
var data = this.Value.GetValueOrDefault().ToOADate();
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(double), this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
double d = BitConverter.ToDouble(value, startIndex);
|
||||
this.Value = Conversions.ConvertDoubleToDateTime(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
WelsonJS.Toolkit/EsentInterop/DoubleColumnValue.cs
Normal file
69
WelsonJS.Toolkit/EsentInterop/DoubleColumnValue.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="DoubleColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="double"/> column value.
|
||||
/// </summary>
|
||||
public class DoubleColumnValue : ColumnValueOfStruct<double>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return sizeof(double); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
var data = this.Value.GetValueOrDefault();
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(double), this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
this.Value = BitConverter.ToDouble(value, startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
172
WelsonJS.Toolkit/EsentInterop/DurableCommitCallback.cs
Normal file
172
WelsonJS.Toolkit/EsentInterop/DurableCommitCallback.cs
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="DurableCommitCallback.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Callback for JET_param JET_paramDurableCommitCallback.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Windows8
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
#if !MANAGEDESENT_ON_CORECLR
|
||||
using System.Runtime.CompilerServices;
|
||||
#endif
|
||||
|
||||
using Microsoft.Isam.Esent.Interop.Implementation;
|
||||
|
||||
/// <summary>
|
||||
/// A class which wraps the callback dealing with durable commits.
|
||||
/// </summary>
|
||||
public class DurableCommitCallback : EsentResource
|
||||
{
|
||||
/// <summary>
|
||||
/// API call tracing.
|
||||
/// </summary>
|
||||
private static readonly TraceSwitch TraceSwitch = new TraceSwitch("ESENT DurableCommitCallback", "Wrapper around unmanaged ESENT durable commit callback");
|
||||
|
||||
/// <summary>
|
||||
/// Instance associated with this callback.
|
||||
/// </summary>
|
||||
private JET_INSTANCE instance;
|
||||
|
||||
/// <summary>
|
||||
/// Hold a reference to the delegate so that it doesn't get garbage-collected.
|
||||
/// </summary>
|
||||
private JET_PFNDURABLECOMMITCALLBACK wrappedCallback;
|
||||
|
||||
/// <summary>
|
||||
/// Hold a reference to the delegate so that it doesn't get garbage-collected.
|
||||
/// </summary>
|
||||
[SuppressMessage("Exchange.Performance", "EX0023:DeadVariableDetector", Justification = "Need to hold on to a reference to the callback, so that it does not get garbage collected.")]
|
||||
private NATIVE_JET_PFNDURABLECOMMITCALLBACK wrapperCallback;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DurableCommitCallback"/> class.
|
||||
/// The constructor.
|
||||
/// </summary>
|
||||
/// <param name="instance">
|
||||
/// The instance with which to associate the callback.
|
||||
/// </param>
|
||||
/// <param name="wrappedCallback">
|
||||
/// The managed code callback to call.
|
||||
/// </param>
|
||||
public DurableCommitCallback(
|
||||
JET_INSTANCE instance,
|
||||
JET_PFNDURABLECOMMITCALLBACK wrappedCallback)
|
||||
{
|
||||
this.instance = instance;
|
||||
this.wrappedCallback = wrappedCallback;
|
||||
this.wrapperCallback = this.NativeDurableCommitCallback;
|
||||
|
||||
#if !MANAGEDESENT_ON_WSA // RuntimeHelpers works differently in Windows Store Apps.
|
||||
if (this.wrappedCallback != null)
|
||||
{
|
||||
RuntimeHelpers.PrepareMethod(this.wrappedCallback.Method.MethodHandle);
|
||||
}
|
||||
|
||||
RuntimeHelpers.PrepareMethod(typeof(DurableCommitCallback).GetMethod("NativeDurableCommitCallback", BindingFlags.NonPublic | BindingFlags.Instance).MethodHandle);
|
||||
#endif
|
||||
|
||||
InstanceParameters instanceParameters = new InstanceParameters(this.instance);
|
||||
|
||||
// This might be null.
|
||||
instanceParameters.SetDurableCommitCallback(this.wrapperCallback);
|
||||
|
||||
this.ResourceWasAllocated();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a string representation of the structure.
|
||||
/// </summary>
|
||||
/// <returns>The structure as a string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"DurableCommitCallback({0})",
|
||||
this.instance.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Terminate the durable commit session.
|
||||
/// </summary>
|
||||
public void End()
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
this.ReleaseResource();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free the durable commit session.
|
||||
/// We do not try to set the instance parameter to null, since the callback is disposed after JetTerm and
|
||||
/// the callback cannot be set after JetTerm.
|
||||
/// </summary>
|
||||
protected override void ReleaseResource()
|
||||
{
|
||||
this.instance = JET_INSTANCE.Nil;
|
||||
this.wrappedCallback = null;
|
||||
this.wrapperCallback = null;
|
||||
this.ResourceWasReleased();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The proxy callback function to call the user-defined managed delegate.
|
||||
/// </summary>
|
||||
/// <param name="instance">
|
||||
/// The instance.
|
||||
/// </param>
|
||||
/// <param name="commitIdSeen">
|
||||
/// The commit-id flushed.
|
||||
/// </param>
|
||||
/// <param name="grbit">
|
||||
/// Reserved currently.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// An error code.
|
||||
/// </returns>
|
||||
private JET_err NativeDurableCommitCallback(
|
||||
IntPtr instance,
|
||||
ref NATIVE_COMMIT_ID commitIdSeen,
|
||||
uint grbit)
|
||||
{
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
JET_INSTANCE jetInstance = new JET_INSTANCE()
|
||||
{
|
||||
Value = instance
|
||||
};
|
||||
|
||||
if (this.instance != jetInstance)
|
||||
{
|
||||
// We assume it's only called on one instance at a time. The only thing
|
||||
// we really care about is serialization of the byte array.
|
||||
//
|
||||
// It would be nice to throw an error, but we're going back to real
|
||||
// code, which doesn't deal with managed exceptions well.
|
||||
return JET_err.CallbackFailed;
|
||||
}
|
||||
|
||||
JET_COMMIT_ID commitId = new JET_COMMIT_ID(commitIdSeen);
|
||||
|
||||
return this.wrappedCallback(jetInstance, commitId, (DurableCommitCallbackGrbit)grbit);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLineIf(
|
||||
TraceSwitch.TraceWarning, string.Format(CultureInfo.InvariantCulture, "Caught Exception {0}", ex));
|
||||
|
||||
JetApi.ReportUnhandledException(ex, "Unhandled exception during NativeDurableCommitCallback");
|
||||
|
||||
// This should never be executed, but the compiler doesn't know it.
|
||||
return JET_err.CallbackFailed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
121
WelsonJS.Toolkit/EsentInterop/EnumeratedColumn.cs
Normal file
121
WelsonJS.Toolkit/EsentInterop/EnumeratedColumn.cs
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EnumeratedColumn.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
/// <summary>
|
||||
/// The values for a given column as generated by Api.EnumerateColumns.
|
||||
/// </summary>
|
||||
public class EnumeratedColumn
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the column ID of this set of column values.
|
||||
/// </summary>
|
||||
public JET_COLUMNID Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status of this column id.
|
||||
/// </summary>
|
||||
/// <seealso cref="JET_err.Success"/>
|
||||
/// <seealso cref="JET_err.BadColumnId"/>
|
||||
/// <seealso cref="JET_err.ColumnNotFound"/>
|
||||
public JET_err Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status of this set of column values.
|
||||
/// </summary>
|
||||
/// <seealso cref="JET_wrn.Success"/>
|
||||
/// <seealso cref="JET_wrn.ColumnDefault"/>
|
||||
/// <seealso cref="JET_wrn.ColumnNull"/>
|
||||
/// <seealso cref="JET_wrn.ColumnPresent"/>
|
||||
/// <seealso cref="JET_wrn.ColumnSkipped"/>
|
||||
public JET_wrn Warning { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column values enumerated.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will be null if the column is null or the column values were not provided.
|
||||
/// </remarks>
|
||||
public Value[] Values { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="EnumeratedColumn"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="EnumeratedColumn"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"EnumeratedColumn(0x{0:x}: {1} Values[{2}])",
|
||||
this.Id,
|
||||
this.Error != JET_err.Success ? this.Error.ToString() : this.Warning.ToString(),
|
||||
this.Values.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A single column value.
|
||||
/// </summary>
|
||||
public class Value
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the ordinal of this column value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The lowest valid ordinal is one.
|
||||
/// This is the same as the "itagSequence" of the column value.
|
||||
/// </remarks>
|
||||
public int Ordinal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status of this column value.
|
||||
/// </summary>
|
||||
/// <seealso cref="JET_wrn.Success"/>
|
||||
/// <seealso cref="JET_wrn.ColumnDefault"/>
|
||||
/// <seealso cref="JET_wrn.ColumnNotInRecord"/>
|
||||
/// <seealso cref="JET_wrn.ColumnNull"/>
|
||||
/// <seealso cref="JET_wrn.ColumnPresent"/>
|
||||
/// <seealso cref="JET_wrn.ColumnSkipped"/>
|
||||
/// <seealso cref="JET_wrn.ColumnTruncated"/>
|
||||
public JET_wrn Warning { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column value as bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This will be null if the column is null or the column values were not provided.
|
||||
/// This will be truncated if Warning is <see cref="JET_wrn.ColumnTruncated"/>.
|
||||
/// </remarks>
|
||||
public byte[] Bytes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="EnumeratedColumn.Value"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="EnumeratedColumn.Value"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
const int MaxLength = 16;
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"EnumeratedColumn.Value({0}: {1} Bytes[{2}] = {3}{4}{5}{6})",
|
||||
this.Ordinal,
|
||||
this.Warning,
|
||||
this.Bytes.Length,
|
||||
'{',
|
||||
BitConverter.ToString(this.Bytes, 0, Math.Min(this.Bytes.Length, MaxLength)),
|
||||
this.Bytes.Length > MaxLength ? "..." : string.Empty,
|
||||
'}');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14038
WelsonJS.Toolkit/EsentInterop/ErrorExceptions.cs
Normal file
14038
WelsonJS.Toolkit/EsentInterop/ErrorExceptions.cs
Normal file
File diff suppressed because it is too large
Load Diff
351
WelsonJS.Toolkit/EsentInterop/Esent.sln
Normal file
351
WelsonJS.Toolkit/EsentInterop/Esent.sln
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.10.35122.118
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{18B3E50E-454E-49DB-A92F-E1D7DAD2AF7D}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
CodeCoverage.testrunconfig = CodeCoverage.testrunconfig
|
||||
esent.vsmdi = esent.vsmdi
|
||||
Normal.testrunconfig = Normal.testrunconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EsentInterop", "EsentInterop.csproj", "{E929E163-52A0-4AAC-917B-6D7FAF70C45E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DbUtil", "..\EsentInteropSamples\DbUtil\DbUtil.csproj", "{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "isam", "..\isam\isam.csproj", "{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StockSample", "..\EsentInteropSamples\StockSample\StockSample.csproj", "{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EsentCollections", "..\EsentCollections\EsentCollections.csproj", "{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloWorld", "..\EsentCollectionsSamples\HelloWorld\HelloWorld.csproj", "{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RssDictionarySample", "..\EsentCollectionsSamples\RssDictionarySample\RssDictionarySample.csproj", "{134FBC80-2E23-451B-A6B3-72B0AA2234F9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EsentInteropTests", "..\EsentInteropTests\EsentInteropTests.csproj", "{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EsentCollectionsTests", "..\EsentCollectionsTests\EsentCollectionsTests.csproj", "{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IsamUnitTests", "..\isamunittests\IsamUnitTests.csproj", "{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DbUtilTests", "..\EsentInteropSamples\DbUtilTests\DbUtilTests.csproj", "{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EsentSample", "..\EsentInteropSamples\EsentSample\EsentSample.csproj", "{44D46916-891F-435F-B914-AE8AC80613FD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicTest", "..\EsentInteropSamples\BasicTest\BasicTest.csproj", "{08819B49-02B8-4F93-A143-F9B0461CEA64}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UWPSample", "..\UWPSample\UWPSample.csproj", "{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Release|x86.ActiveCfg = Release|x86
|
||||
{E929E163-52A0-4AAC-917B-6D7FAF70C45E}.Release|x86.Build.0 = Release|x86
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Release|x86.ActiveCfg = Release|x86
|
||||
{E0B163B0-5AC6-4304-B932-BFC1F6A2A4EB}.Release|x86.Build.0 = Release|x86
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Release|x86.ActiveCfg = Release|x86
|
||||
{21CC632C-B09A-4DB7-BD6E-7F7D2716F58F}.Release|x86.Build.0 = Release|x86
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Release|x86.ActiveCfg = Release|x86
|
||||
{B0E6D3AB-26F8-4A77-A7E1-D8024B8FFFCF}.Release|x86.Build.0 = Release|x86
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Release|x86.ActiveCfg = Release|x86
|
||||
{CF2D4EE4-0D11-404D-B800-C4DCFEC42588}.Release|x86.Build.0 = Release|x86
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Release|x86.ActiveCfg = Release|x86
|
||||
{8341DE8C-5BC7-461F-B42D-AA2B72586A5C}.Release|x86.Build.0 = Release|x86
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Release|x64.Build.0 = Release|Any CPU
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Release|x86.ActiveCfg = Release|x86
|
||||
{134FBC80-2E23-451B-A6B3-72B0AA2234F9}.Release|x86.Build.0 = Release|x86
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Release|x86.ActiveCfg = Release|x86
|
||||
{85B2B7BB-BF95-42DF-8CBF-348AEF63BD1F}.Release|x86.Build.0 = Release|x86
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Release|x86.ActiveCfg = Release|x86
|
||||
{D3A1C1C8-6119-4827-AC24-1FF49FACFD4D}.Release|x86.Build.0 = Release|x86
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Release|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Release|x86.ActiveCfg = Release|x86
|
||||
{6AC9C0BE-6BCE-493F-BD80-6F2247CB669D}.Release|x86.Build.0 = Release|x86
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Release|x86.ActiveCfg = Release|x86
|
||||
{C9B82A4F-8306-41A9-91DA-1BA5080F1DB0}.Release|x86.Build.0 = Release|x86
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Release|x64.Build.0 = Release|Any CPU
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Release|x86.ActiveCfg = Release|x86
|
||||
{44D46916-891F-435F-B914-AE8AC80613FD}.Release|x86.Build.0 = Release|x86
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Release|x64.Build.0 = Release|Any CPU
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Release|x86.ActiveCfg = Release|x86
|
||||
{08819B49-02B8-4F93-A143-F9B0461CEA64}.Release|x86.Build.0 = Release|x86
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|x64.Build.0 = Debug|x64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|x86.Build.0 = Debug|x86
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|ARM.Build.0 = Release|ARM
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|x64.ActiveCfg = Release|x64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|x64.Build.0 = Release|x64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|x64.Deploy.0 = Release|x64
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|x86.ActiveCfg = Release|x86
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|x86.Build.0 = Release|x86
|
||||
{B1427E8D-9175-42BE-8B90-A5A9CB4AAD51}.Release|x86.Deploy.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {6A6764EF-3A8F-46BF-8CC8-C07DE889160A}
|
||||
EndGlobalSection
|
||||
GlobalSection(TestCaseManagementSettings) = postSolution
|
||||
CategoryFile = Esent.vsmdi
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
6
WelsonJS.Toolkit/EsentInterop/Esent.vsmdi
Normal file
6
WelsonJS.Toolkit/EsentInterop/Esent.vsmdi
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
|
||||
<TestList name="Lists of Tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
|
||||
<RunConfiguration id="6c3d561f-b13d-4563-9e69-90f00c61747b" name="Normal" storage="normal.testrunconfig" type="Microsoft.VisualStudio.TestTools.Common.TestRunConfiguration, Microsoft.VisualStudio.QualityTools.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
</TestList>
|
||||
</TestLists>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><ItemProperties xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Properties><Property><Name>svn:mime-type</Name><Value>application/octet-stream</Value></Property></Properties></ItemProperties>
|
||||
82
WelsonJS.Toolkit/EsentInterop/Esent/AssemblyInfo.cs
Normal file
82
WelsonJS.Toolkit/EsentInterop/Esent/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="AssemblyInfo.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("EsentInterop")]
|
||||
[assembly: AssemblyDescription("Managed interop code for esent.dll")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyProduct("EsentInterop")]
|
||||
[assembly: AssemblyCopyright("Copyright (c) Microsoft")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
[assembly: CLSCompliant(true)]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
//
|
||||
// Version history:
|
||||
// 1.6.0.0
|
||||
// 1.7.0.0
|
||||
// 1.8.0.0 Support new Windows user interface (As of Win8 Beta build).
|
||||
// 1.8.1.0 2012.11.18. Some minor updates, including some perf updates.
|
||||
// 1.8.2.0 2012.11.19. Signed.
|
||||
// 1.8.3.0 2013.03.25. Signed and Strong Named. Renamed 'Metro' to 'Wsa' (Windows Store App)
|
||||
// 1.8.4.0 2013.12.23. Updated for Windows 8.1.
|
||||
// 1.9.0.0 2013.12.23. Go back to targetting framework 4.0.
|
||||
// 1.9.1.0 2014.07.18. PersistentDictionary gets binary blobs; added Isam layer.
|
||||
// 1.9.2.0 2014.09.11. Isam is placed in the Microsoft.Database namespace.
|
||||
// 1.9.3.0 2015.08.11. Dependence added from Collections to Isam dll for configsets.
|
||||
// 1.9.3.2 2015.09.02. Some bug fixes; go back to Framework 4.0
|
||||
// 1.9.3.3 2016.03.01. Some bug and perf fixes.
|
||||
// 1.9.4 2016.06.28. Some bug fixes.
|
||||
// 1.9.4.1 2017.08.30. Adding JetGetIndexInfo that returns JET_INDEXCREATE.
|
||||
[assembly: AssemblyVersion("1.9.4.1")]
|
||||
[assembly: AssemblyFileVersion("1.9.4.1")]
|
||||
|
||||
#if STRONG_NAMED
|
||||
[assembly: InternalsVisibleTo("EsentInteropWsaTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9")]
|
||||
[assembly: InternalsVisibleTo("Esent.Isam, PublicKey=0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9")]
|
||||
[assembly: InternalsVisibleTo("InteropApiTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9")]
|
||||
[assembly: InternalsVisibleTo("IsamUnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9")]
|
||||
[assembly: InternalsVisibleTo("Pixie, PublicKey=0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9")]
|
||||
[assembly: InternalsVisibleTo("PixieTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9")]
|
||||
|
||||
// This assembly is generated by Rhino.Mocks
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2,PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
#else
|
||||
[assembly: InternalsVisibleTo("InteropApiTests")]
|
||||
[assembly: InternalsVisibleTo("IsamUnitTests")]
|
||||
[assembly: InternalsVisibleTo("EsentInteropTestsImmersive")]
|
||||
[assembly: InternalsVisibleTo("EsentInteropWsaTests")]
|
||||
[assembly: InternalsVisibleTo("Esent.Isam")]
|
||||
[assembly: InternalsVisibleTo("Pixie")]
|
||||
[assembly: InternalsVisibleTo("PixieTests")]
|
||||
|
||||
// This assembly is generated by Rhino.Mocks
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
#endif
|
||||
37
WelsonJS.Toolkit/EsentInterop/Esent/CallbackDataConverter.cs
Normal file
37
WelsonJS.Toolkit/EsentInterop/Esent/CallbackDataConverter.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="CallbackDataConverter.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
/// <summary>
|
||||
/// Methods to convert data objects used in callbacks.
|
||||
/// </summary>
|
||||
internal static class CallbackDataConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the managed data object from the unmanaged data.
|
||||
/// </summary>
|
||||
/// <param name="nativeData">The native data.</param>
|
||||
/// <param name="snp">The SNP (used to determine the type of object).</param>
|
||||
/// <param name="snt">The SNT (used to determine the type of object).</param>
|
||||
/// <returns>The managed data object.</returns>
|
||||
public static object GetManagedData(IntPtr nativeData, JET_SNP snp, JET_SNT snt)
|
||||
{
|
||||
if (IntPtr.Zero != nativeData && JET_SNT.Progress == snt)
|
||||
{
|
||||
NATIVE_SNPROG native = (NATIVE_SNPROG)Marshal.PtrToStructure(nativeData, typeof(NATIVE_SNPROG));
|
||||
JET_SNPROG managed = new JET_SNPROG();
|
||||
managed.SetFromNative(native);
|
||||
return managed;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
263
WelsonJS.Toolkit/EsentInterop/Esent/EsentImplementationStubs.cs
Normal file
263
WelsonJS.Toolkit/EsentInterop/Esent/EsentImplementationStubs.cs
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EsentImplementationStubs.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Class stubs to allow compiling on CoreClr.
|
||||
// </summary>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Implementation
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// A fake class to allow compilation on platforms that lack this functionality.
|
||||
/// </summary>
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "Reviewed. Suppression is OK here because it's a collection of trivial classes.")]
|
||||
public class Trace
|
||||
{
|
||||
/// <summary>
|
||||
/// A fake function to allow compilation on platforms that lack this functionality.
|
||||
/// </summary>
|
||||
/// <param name="condition">
|
||||
/// The condition.
|
||||
/// </param>
|
||||
/// <param name="message">
|
||||
/// The message.
|
||||
/// </param>
|
||||
[ConditionalAttribute("TRACE")]
|
||||
public static void WriteLineIf(bool condition, string message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake function to allow compilation on platforms that lack this functionality.
|
||||
/// </summary>
|
||||
/// <param name="condition">
|
||||
/// The condition.
|
||||
/// </param>
|
||||
/// <param name="message">
|
||||
/// The message.
|
||||
/// </param>
|
||||
[ConditionalAttribute("TRACE")]
|
||||
public static void WriteLineIf(bool condition, object message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prints out the object's contents.
|
||||
/// </summary>
|
||||
/// <returns>A string represenetation or the object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake class to allow compilation on platforms that lack this class.
|
||||
/// </summary>
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "Reviewed. Suppression is OK here because it's a collection of trivial classes.")]
|
||||
internal static class RuntimeHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// A fake function to allow compilation on platforms that lack this functionality.
|
||||
/// </summary>
|
||||
public static void PrepareConstrainedRegions()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake function to allow compilation on platforms that lack this functionality.
|
||||
/// </summary>
|
||||
/// <param name="method">
|
||||
/// The method.
|
||||
/// </param>
|
||||
public static void PrepareMethod(RuntimeMethodHandle method)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ascii encoding is not available on Core Clr. But UTF-8 is.
|
||||
/// This class will reject any character that results in an
|
||||
/// extended value.
|
||||
/// </summary>
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "Reviewed. Suppression is OK here because it's a collection of trivial classes.")]
|
||||
internal class SlowAsciiEncoding : UTF8Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// The standard encoding object.
|
||||
/// </summary>
|
||||
private static SlowAsciiEncoding slowAsciiEncoding = new SlowAsciiEncoding();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an Encoding object.
|
||||
/// </summary>
|
||||
public static Encoding Encoding
|
||||
{
|
||||
get
|
||||
{
|
||||
return slowAsciiEncoding;
|
||||
}
|
||||
}
|
||||
|
||||
#if !MANAGEDESENT_ON_WSA
|
||||
/// <summary>
|
||||
/// Converts a string to the byte representation.
|
||||
/// </summary>
|
||||
/// <param name="chars">
|
||||
/// The chars.
|
||||
/// </param>
|
||||
/// <param name="charCount">
|
||||
/// The char count.
|
||||
/// </param>
|
||||
/// <param name="bytes">
|
||||
/// The bytes.
|
||||
/// </param>
|
||||
/// <param name="byteCount">
|
||||
/// The byte count.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A count of bytes stored.
|
||||
/// </returns>
|
||||
public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
|
||||
{
|
||||
IntPtr toFree;
|
||||
char* charsToTranslate = this.SanitizeString(chars, charCount, out toFree);
|
||||
|
||||
int toReturn = base.GetBytes(charsToTranslate, charCount, bytes, byteCount);
|
||||
LibraryHelpers.MarshalFreeHGlobal(toFree);
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to the byte representation.
|
||||
/// </summary>
|
||||
/// <param name="inputString">
|
||||
/// The input string.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The byte representation of the string.
|
||||
/// </returns>
|
||||
public override byte[] GetBytes(string inputString)
|
||||
{
|
||||
string stringToTranslate = this.SanitizeString(inputString);
|
||||
return base.GetBytes(stringToTranslate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to the byte representation.
|
||||
/// </summary>
|
||||
/// <param name="inputString">
|
||||
/// The input string.
|
||||
/// </param>
|
||||
/// <param name="charIndex">
|
||||
/// The char index.
|
||||
/// </param>
|
||||
/// <param name="charCount">
|
||||
/// The char count.
|
||||
/// </param>
|
||||
/// <param name="bytes">
|
||||
/// The bytes.
|
||||
/// </param>
|
||||
/// <param name="byteIndex">
|
||||
/// The byte index.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The byte representation of the string.
|
||||
/// </returns>
|
||||
public override int GetBytes(string inputString, int charIndex, int charCount, byte[] bytes, int byteIndex)
|
||||
{
|
||||
string stringToTranslate = this.SanitizeString(inputString);
|
||||
|
||||
return base.GetBytes(stringToTranslate, charIndex, charCount, bytes, byteIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scans the string looking for unmappable characters in the ASCII set, and replaces
|
||||
/// them with '?'.
|
||||
/// </summary>
|
||||
/// <param name="inputString">A unicode string with unknown characters.</param>
|
||||
/// <returns>A string that has all legal ASCII characters.</returns>
|
||||
private string SanitizeString(string inputString)
|
||||
{
|
||||
bool needToDuplicate = false;
|
||||
string returnString = inputString;
|
||||
|
||||
foreach (char ch in inputString)
|
||||
{
|
||||
if (ch > 127)
|
||||
{
|
||||
needToDuplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needToDuplicate)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(inputString.Length);
|
||||
foreach (char ch in inputString)
|
||||
{
|
||||
sb.Append(ch > 127 ? '?' : ch);
|
||||
}
|
||||
|
||||
returnString = sb.ToString();
|
||||
}
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
#if !MANAGEDESENT_ON_WSA
|
||||
/// <summary>
|
||||
/// Scans the string looking for unmappable characters in the ASCII set, and replaces
|
||||
/// them with '?'.
|
||||
/// </summary>
|
||||
/// <param name="inputString">A unicode string with unknown characters.</param>
|
||||
/// <param name="charCount">The length of the string to sanitize.</param>
|
||||
/// <param name="allocedMemory">On output, a value that needs to be freed. Only used
|
||||
/// if there are any untranslaable characters.</param>
|
||||
/// <returns>A string that has all legal ASCII characters.</returns>
|
||||
private unsafe char* SanitizeString(char* inputString, int charCount, out IntPtr allocedMemory)
|
||||
{
|
||||
allocedMemory = IntPtr.Zero;
|
||||
|
||||
bool needToDuplicate = false;
|
||||
char* returnString = inputString;
|
||||
|
||||
for (int i = 0; i < charCount; ++i)
|
||||
{
|
||||
if (inputString[i] > 127)
|
||||
{
|
||||
needToDuplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needToDuplicate)
|
||||
{
|
||||
allocedMemory = LibraryHelpers.MarshalAllocHGlobal(charCount);
|
||||
returnString = (char*)allocedMemory;
|
||||
|
||||
char* dest = returnString;
|
||||
|
||||
for (int i = 0; i < charCount; ++i)
|
||||
{
|
||||
dest[i] = inputString[i] > 127 ? '?' : inputString[i];
|
||||
}
|
||||
}
|
||||
|
||||
return returnString;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
157
WelsonJS.Toolkit/EsentInterop/Esent/EsentJetApi.cs
Normal file
157
WelsonJS.Toolkit/EsentInterop/Esent/EsentJetApi.cs
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EsentJetApi.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// JetApi code that is specific to ESENT.
|
||||
// </summary>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Implementation
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// JetApi code that is specific to ESENT.
|
||||
/// </summary>
|
||||
internal sealed partial class JetApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Reports the exception to a central authority.
|
||||
/// </summary>
|
||||
/// <param name="exception">An unhandled exception.</param>
|
||||
/// <param name="description">A string description of the scenario.</param>
|
||||
internal static void ReportUnhandledException(
|
||||
Exception exception,
|
||||
string description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the capabilities of the current Esent version.
|
||||
/// </summary>
|
||||
private void DetermineCapabilities()
|
||||
{
|
||||
const int Server2003BuildNumber = 2700;
|
||||
const int VistaBuildNumber = 6000;
|
||||
const int Windows7BuildNumber = 7000; // includes beta as well as RTM (RTM is 7600)
|
||||
const int Windows8BuildNumber = 8000; // includes beta as well as RTM (RTM is 9200)
|
||||
const int Windows81BuildNumber = 9300; // includes beta as well as RTM (RTM is 9600)
|
||||
const int Windows10BuildNumber = 9900; // includes beta as well as RTM (RTM is 10240)
|
||||
|
||||
// Create new capabilities, set as all false. This will allow
|
||||
// us to call into Esent.
|
||||
this.Capabilities = new JetCapabilities { ColumnsKeyMost = 12 };
|
||||
|
||||
var version = this.versionOverride;
|
||||
if (version == 0)
|
||||
{
|
||||
version = this.GetVersionFromEsent();
|
||||
}
|
||||
|
||||
var buildNumber = (int)((version & 0xFFFFFF) >> 8);
|
||||
|
||||
Trace.WriteLineIf(
|
||||
TraceSwitch.TraceVerbose,
|
||||
string.Format(CultureInfo.InvariantCulture, "Version = {0}, BuildNumber = {1}", version, buildNumber));
|
||||
|
||||
if (buildNumber >= Server2003BuildNumber)
|
||||
{
|
||||
Trace.WriteLineIf(TraceSwitch.TraceVerbose, "Supports Server 2003 features");
|
||||
this.Capabilities.SupportsServer2003Features = true;
|
||||
}
|
||||
|
||||
if (buildNumber >= VistaBuildNumber)
|
||||
{
|
||||
Trace.WriteLineIf(TraceSwitch.TraceVerbose, "Supports Vista features");
|
||||
this.Capabilities.SupportsVistaFeatures = true;
|
||||
|
||||
Trace.WriteLineIf(TraceSwitch.TraceVerbose, "Supports Unicode paths");
|
||||
this.Capabilities.SupportsUnicodePaths = true;
|
||||
|
||||
Trace.WriteLineIf(TraceSwitch.TraceVerbose, "Supports large keys");
|
||||
this.Capabilities.SupportsLargeKeys = true;
|
||||
Trace.WriteLineIf(TraceSwitch.TraceVerbose, "Supports 16-column keys");
|
||||
this.Capabilities.ColumnsKeyMost = 16;
|
||||
}
|
||||
|
||||
if (buildNumber >= Windows7BuildNumber)
|
||||
{
|
||||
Trace.WriteLineIf(TraceSwitch.TraceVerbose, "Supports Windows 7 features");
|
||||
this.Capabilities.SupportsWindows7Features = true;
|
||||
}
|
||||
|
||||
if (buildNumber >= Windows8BuildNumber)
|
||||
{
|
||||
Trace.WriteLineIf(TraceSwitch.TraceVerbose, "Supports Windows 8 features");
|
||||
this.Capabilities.SupportsWindows8Features = true;
|
||||
}
|
||||
|
||||
if (buildNumber >= Windows81BuildNumber)
|
||||
{
|
||||
Trace.WriteLineIf(TraceSwitch.TraceVerbose, "Supports Windows 8.1 features");
|
||||
this.Capabilities.SupportsWindows81Features = true;
|
||||
}
|
||||
|
||||
if (buildNumber >= Windows10BuildNumber)
|
||||
{
|
||||
Trace.WriteLineIf(TraceSwitch.TraceVerbose, "Supports Windows 10 features");
|
||||
this.Capabilities.SupportsWindows10Features = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance and get the current version of Esent.
|
||||
/// </summary>
|
||||
/// <returns>The current version of Esent.</returns>
|
||||
private uint GetVersionFromEsent()
|
||||
{
|
||||
#if MANAGEDESENT_ON_WSA
|
||||
// JetGetVersion isn't available in new Windows user interface, so we'll pretend it's always Win8:
|
||||
return 8250 << 8;
|
||||
#else
|
||||
// Create a unique name so that multiple threads can call this simultaneously.
|
||||
// This can happen if there are multiple AppDomains.
|
||||
string instanceName = string.Format(CultureInfo.InvariantCulture, "GettingEsentVersion{0}", LibraryHelpers.GetCurrentManagedThreadId());
|
||||
JET_INSTANCE instance = JET_INSTANCE.Nil;
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
this.JetCreateInstance(out instance, instanceName);
|
||||
this.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.Recovery, new IntPtr(0), "off");
|
||||
this.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.NoInformationEvent, new IntPtr(1), null);
|
||||
this.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.MaxTemporaryTables, new IntPtr(0), null);
|
||||
this.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.MaxCursors, new IntPtr(16), null);
|
||||
this.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.MaxOpenTables, new IntPtr(16), null);
|
||||
this.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.MaxVerPages, new IntPtr(4), null);
|
||||
this.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.MaxSessions, new IntPtr(1), null);
|
||||
this.JetInit(ref instance);
|
||||
|
||||
JET_SESID sesid;
|
||||
this.JetBeginSession(instance, out sesid, string.Empty, string.Empty);
|
||||
try
|
||||
{
|
||||
uint version;
|
||||
this.JetGetVersion(sesid, out version);
|
||||
return version;
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.JetEndSession(sesid, EndSessionGrbit.None);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (JET_INSTANCE.Nil != instance)
|
||||
{
|
||||
this.JetTerm(instance);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
22
WelsonJS.Toolkit/EsentInterop/Esent/EsentNativeMethods.cs
Normal file
22
WelsonJS.Toolkit/EsentInterop/Esent/EsentNativeMethods.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EsentNativeMethods.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// NativeMethods code that is specific to ESENT.
|
||||
// </summary>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Implementation
|
||||
{
|
||||
/// <summary>
|
||||
/// Configuration for functions in esent.dll.
|
||||
/// </summary>
|
||||
internal static partial class NativeMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the DLL that the methods should be loaded from.
|
||||
/// </summary>
|
||||
private const string EsentDll = "esent.dll";
|
||||
}
|
||||
}
|
||||
325
WelsonJS.Toolkit/EsentInterop/Esent/EsentStubAttributes.cs
Normal file
325
WelsonJS.Toolkit/EsentInterop/Esent/EsentStubAttributes.cs
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EsentStubAttributes.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Attribute stubs to allow compiling on CoreClr.
|
||||
// </summary>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
#if !MANAGEDESENT_ON_WSA
|
||||
This file should only be compiled with MANAGEDESENT_ON_WSA
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// A fake enumeration to allow compilation on platforms that lack this enumeration.
|
||||
/// </summary>
|
||||
public enum SecurityAction
|
||||
{
|
||||
/// <summary>
|
||||
/// A fake enumeration to allow compilation on platforms that lack this enumeration.
|
||||
/// </summary>
|
||||
LinkDemand
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake attribute to allow compilation on platforms that lack this attribute.
|
||||
/// </summary>
|
||||
//// The real one inherits from System.Security.Permissions.CodeAccessSecurityAttribute.
|
||||
[SerializableAttribute]
|
||||
[ComVisibleAttribute(true)]
|
||||
[AttributeUsageAttribute(
|
||||
AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor
|
||||
| AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
|
||||
internal sealed class SecurityPermissionAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SecurityPermissionAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="action">
|
||||
/// The action.
|
||||
/// </param>
|
||||
public SecurityPermissionAttribute(
|
||||
SecurityAction action)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prints out the object's contents.
|
||||
/// </summary>
|
||||
/// <returns>A string represenetation or the object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake attribute to allow compilation on platforms that lack this attribute.
|
||||
/// </summary>
|
||||
[ComVisibleAttribute(true)]
|
||||
[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "Reviewed. Suppression is OK here because it's a collection of trivial classes.")]
|
||||
[SuppressMessage(
|
||||
"Microsoft.StyleCop.CSharp.MaintainabilityRules",
|
||||
"SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "These stub classes are compiled only on some platforms that do not contain the entire framework, e.g. new Windows user interface.")]
|
||||
internal sealed class BestFitMappingAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BestFitMappingAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="bestFitMapping">
|
||||
/// The best fit mapping.
|
||||
/// </param>
|
||||
public BestFitMappingAttribute(
|
||||
bool bestFitMapping)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether ThrowOnUnmappableChar.
|
||||
/// </summary>
|
||||
public bool ThrowOnUnmappableChar
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prints out the object's contents.
|
||||
/// </summary>
|
||||
/// <returns>A string represenetation or the object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake attribute to allow compilation on platforms that lack this attribute.
|
||||
/// </summary>
|
||||
[ComVisibleAttribute(true)]
|
||||
[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = true,
|
||||
Inherited = false)]
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "Reviewed. Suppression is OK here because it's a collection of trivial classes.")]
|
||||
[SuppressMessage(
|
||||
"Microsoft.StyleCop.CSharp.MaintainabilityRules",
|
||||
"SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "These stub classes are compiled only on some platforms that do not contain the entire framework, e.g. new Windows user interface.")]
|
||||
internal sealed class SuppressUnmanagedCodeSecurityAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Prints out the object's contents.
|
||||
/// </summary>
|
||||
/// <returns>A string represenetation or the object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake attribute to allow compilation on platforms that lack this attribute.
|
||||
/// </summary>
|
||||
[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
|
||||
[ComVisibleAttribute(true)]
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "Reviewed. Suppression is OK here because it's a collection of trivial classes.")]
|
||||
[SuppressMessage(
|
||||
"Microsoft.StyleCop.CSharp.MaintainabilityRules",
|
||||
"SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "These stub classes are compiled only on some platforms that do not contain the entire framework, e.g. new Windows user interface.")]
|
||||
internal sealed class ComVisibleAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ComVisibleAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="comVisible">
|
||||
/// The com visible.
|
||||
/// </param>
|
||||
public ComVisibleAttribute(bool comVisible)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prints out the object's contents.
|
||||
/// </summary>
|
||||
/// <returns>A string represenetation or the object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that a class can be serialized. This class cannot be inherited.
|
||||
/// </summary>
|
||||
/// <filterpriority>1</filterpriority>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate, Inherited = false), ComVisible(true)]
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "Reviewed. Suppression is OK here because it's a collection of trivial classes.")]
|
||||
[SuppressMessage(
|
||||
"Microsoft.StyleCop.CSharp.MaintainabilityRules",
|
||||
"SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "These stub classes are compiled only on some platforms that do not contain the entire framework, e.g. new Windows user interface.")]
|
||||
internal sealed class SerializableAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Prints out the object's contents.
|
||||
/// </summary>
|
||||
/// <returns>A string represenetation or the object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that a field of a serializable class should not be serialized. This class cannot be inherited.
|
||||
/// </summary>
|
||||
/// <filterpriority>1</filterpriority>
|
||||
[ComVisible(true), AttributeUsage(AttributeTargets.Field, Inherited = false)]
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "Reviewed. Suppression is OK here because it's a collection of trivial classes.")]
|
||||
[SuppressMessage(
|
||||
"Microsoft.StyleCop.CSharp.MaintainabilityRules",
|
||||
"SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "These stub classes are compiled only on some platforms that do not contain the entire framework, e.g. new Windows user interface.")]
|
||||
internal sealed class NonSerializedAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Prints out the object's contents.
|
||||
/// </summary>
|
||||
/// <returns>A string represenetation or the object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace System.Runtime.ConstrainedExecution
|
||||
{
|
||||
}
|
||||
|
||||
namespace System.Security.Cryptography
|
||||
{
|
||||
}
|
||||
|
||||
namespace System.Security.Permissions
|
||||
{
|
||||
}
|
||||
|
||||
namespace Microsoft.Win32.SafeHandles
|
||||
{
|
||||
}
|
||||
|
||||
namespace System.Runtime.ConstrainedExecution
|
||||
{
|
||||
using System;
|
||||
using Microsoft.Isam.Esent.Interop;
|
||||
|
||||
/// <summary>
|
||||
/// The consistency model. A stub.
|
||||
/// </summary>
|
||||
internal enum Consistency
|
||||
{
|
||||
/// <summary>
|
||||
/// Might corrupt the process.
|
||||
/// </summary>
|
||||
MayCorruptProcess,
|
||||
|
||||
/// <summary>
|
||||
/// Might corrupt the application domain.
|
||||
/// </summary>
|
||||
MayCorruptAppDomain,
|
||||
|
||||
/// <summary>
|
||||
/// Might corrupt the instance.
|
||||
/// </summary>
|
||||
MayCorruptInstance,
|
||||
|
||||
/// <summary>
|
||||
/// Will not corrupt the state.
|
||||
/// </summary>
|
||||
WillNotCorruptState,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Crticial Execution Region description. A stub.
|
||||
/// </summary>
|
||||
internal enum Cer
|
||||
{
|
||||
/// <summary>
|
||||
/// No options.
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// This might fail.
|
||||
/// </summary>
|
||||
MayFail,
|
||||
|
||||
/// <summary>
|
||||
/// A successful CER.
|
||||
/// </summary>
|
||||
Success,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The description of the reliability contract. A stub.
|
||||
/// </summary>
|
||||
internal sealed class ReliabilityContractAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// The consistency guarantee. A stub.
|
||||
/// </summary>
|
||||
private Consistency consistency;
|
||||
|
||||
/// <summary>
|
||||
/// The critical execution region. A stub.
|
||||
/// </summary>
|
||||
private Cer cer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ReliabilityContractAttribute class. A stub.
|
||||
/// </summary>
|
||||
/// <param name="consistencyGuarantee">The guarantee of the consistency.</param>
|
||||
/// <param name="cer">The critical execution region description.</param>
|
||||
public ReliabilityContractAttribute(Consistency consistencyGuarantee, Cer cer)
|
||||
{
|
||||
this.consistency = consistencyGuarantee;
|
||||
this.cer = cer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the consistency guarantee. A stub.
|
||||
/// </summary>
|
||||
public Consistency ConsistencyGuarantee
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.consistency;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the critical execution region. A stub.
|
||||
/// </summary>
|
||||
public Cer Cer
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.cer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
273
WelsonJS.Toolkit/EsentInterop/Esent/EsentStubs.cs
Normal file
273
WelsonJS.Toolkit/EsentInterop/Esent/EsentStubs.cs
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EsentStubs.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Class stubs to allow compiling on CoreClr.
|
||||
// </summary>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
/// <summary>
|
||||
/// Some useful functionality that was omitted from Core CLR classes.
|
||||
/// </summary>
|
||||
[SuppressMessage(
|
||||
"Microsoft.StyleCop.CSharp.MaintainabilityRules",
|
||||
"SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "These stub classes are compiled only on some platforms that do not contain the entire framework, e.g. new Windows user interface.")]
|
||||
public static class ExtensionsToCoreClr
|
||||
{
|
||||
/// <summary>Converts the value of this instance to the equivalent OLE Automation date.</summary>
|
||||
/// <param name="dateTime">A DateTime structure.</param>
|
||||
/// <returns>A double-precision floating-point number that contains an OLE Automation date equivalent to the value of this instance.</returns>
|
||||
/// <exception cref="T:System.OverflowException">The value of this instance cannot be represented as an OLE Automation Date. </exception>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
public static double ToOADate(this DateTime dateTime)
|
||||
{
|
||||
return LibraryHelpers.TicksToOADate(dateTime.Ticks);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// JetApi code that is specific to ESENT.
|
||||
/// </summary>
|
||||
[SuppressMessage(
|
||||
"Microsoft.StyleCop.CSharp.MaintainabilityRules",
|
||||
"SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "These stub classes are compiled only on some platforms that do not contain the entire framework, e.g. new Windows user interface.")]
|
||||
public class SerializationInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Prints out the object's contents.
|
||||
/// </summary>
|
||||
/// <returns>A string represenetation or the object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes an integer.
|
||||
/// </summary>
|
||||
/// <param name="propName">The name of the field to retrieve.</param>
|
||||
/// <returns>An integer.</returns>
|
||||
public int GetInt32(string propName)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake class to allow compilation on platforms that lack this class.
|
||||
/// </summary>
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "Reviewed. Suppression is OK here because it's a collection of trivial classes.")]
|
||||
[SuppressMessage(
|
||||
"Microsoft.StyleCop.CSharp.MaintainabilityRules",
|
||||
"SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "These stub classes are compiled only on some platforms that do not contain the entire framework, e.g. new Windows user interface.")]
|
||||
internal static class RuntimeHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// A fake function to allow compilation on platforms that lack this functionality.
|
||||
/// </summary>
|
||||
public static void PrepareConstrainedRegions()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake function to allow compilation on platforms that lack this functionality.
|
||||
/// </summary>
|
||||
/// <param name="method">
|
||||
/// The method.
|
||||
/// </param>
|
||||
public static void PrepareMethod(RuntimeMethodHandle method)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake class to allow compilation on platforms that lack this class.
|
||||
/// </summary>
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "Reviewed. Suppression is OK here because it's a collection of trivial classes.")]
|
||||
internal class TraceSwitch
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TraceSwitch"/> class.
|
||||
/// </summary>
|
||||
/// <param name="displayName">
|
||||
/// The display name.
|
||||
/// </param>
|
||||
/// <param name="description">
|
||||
/// The description.
|
||||
/// </param>
|
||||
public TraceSwitch(string displayName, string description)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether TraceVerbose.
|
||||
/// </summary>
|
||||
public bool TraceVerbose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether TraceWarning.
|
||||
/// </summary>
|
||||
public bool TraceWarning { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether TraceError.
|
||||
/// </summary>
|
||||
public bool TraceError { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether TraceInfo.
|
||||
/// </summary>
|
||||
public bool TraceInfo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Prints out the object's contents.
|
||||
/// </summary>
|
||||
/// <returns>A string represenetation or the object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake class to allow compilation on platforms that lack this class.
|
||||
/// </summary>
|
||||
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass",
|
||||
Justification = "Reviewed. Suppression is OK here because it's a collection of trivial classes.")]
|
||||
internal class Trace
|
||||
{
|
||||
/// <summary>
|
||||
/// A fake function to allow compilation on platforms that lack this functionality.
|
||||
/// </summary>
|
||||
/// <param name="condition">
|
||||
/// The condition.
|
||||
/// </param>
|
||||
/// <param name="message">
|
||||
/// The message.
|
||||
/// </param>
|
||||
[ConditionalAttribute("TRACE")]
|
||||
public static void WriteLineIf(bool condition, string message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake function to allow compilation on platforms that lack this functionality.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// The message.
|
||||
/// </param>
|
||||
[ConditionalAttribute("TRACE")]
|
||||
public static void TraceError(string message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A fake function to allow compilation on platforms that lack this functionality.
|
||||
/// </summary>
|
||||
/// <param name="message">
|
||||
/// The message.
|
||||
/// </param>
|
||||
/// <param name="args">
|
||||
/// The arguments.
|
||||
/// </param>
|
||||
[ConditionalAttribute("TRACE")]
|
||||
public static void TraceWarning(string message, params object[] args)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if MANAGEDESENT_ON_WSA
|
||||
namespace System.ComponentModel
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
/// <summary>
|
||||
/// An exception from a Win32 call.
|
||||
/// </summary>
|
||||
//// The original derives from System.Runtime.InteropServices.ExternalException.
|
||||
internal class Win32Exception : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// The error code from a Win32 call.
|
||||
/// </summary>
|
||||
private readonly int nativeErrorCode;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Win32Exception class.
|
||||
/// </summary>
|
||||
[SecuritySafeCritical]
|
||||
public Win32Exception() : this(Marshal.GetLastWin32Error())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Win32Exception class.
|
||||
/// </summary>
|
||||
/// <param name="error">A win32 error code.</param>
|
||||
[SecuritySafeCritical]
|
||||
public Win32Exception(int error) : this(error, Win32Exception.GetErrorMessage(error))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Win32Exception class.
|
||||
/// </summary>
|
||||
/// <param name="error">A win32 error code.</param>
|
||||
/// <param name="message">The string message.</param>
|
||||
public Win32Exception(int error, string message)
|
||||
: base(message)
|
||||
{
|
||||
this.nativeErrorCode = error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Win32Exception class.
|
||||
/// </summary>
|
||||
/// <param name="message">The string message.</param>
|
||||
[SecuritySafeCritical]
|
||||
public Win32Exception(string message) : this(Marshal.GetLastWin32Error(), message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Win32Exception class.
|
||||
/// </summary>
|
||||
/// <param name="message">The string message.</param>
|
||||
/// <param name="innerException">The nested exception.</param>
|
||||
[SecuritySafeCritical, SuppressMessage("Microsoft.Interoperability", "CA1404:CallGetLastErrorImmediatelyAfterPInvoke", Justification = "Retuning error codes.")]
|
||||
public Win32Exception(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
this.nativeErrorCode = Marshal.GetLastWin32Error();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string value of the Win32 error code.
|
||||
/// </summary>
|
||||
/// <param name="error">The Win32 error code.</param>
|
||||
/// <returns>A string representation.</returns>
|
||||
[SecuritySafeCritical]
|
||||
private static string GetErrorMessage(int error)
|
||||
{
|
||||
string result = string.Empty;
|
||||
result = "Win32 error (0x" + Convert.ToString(error, 16) + ")";
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // MANAGEDESENT_ON_WSA
|
||||
BIN
WelsonJS.Toolkit/EsentInterop/Esent/ManagedEseLogo128x128.png
Normal file
BIN
WelsonJS.Toolkit/EsentInterop/Esent/ManagedEseLogo128x128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
2921
WelsonJS.Toolkit/EsentInterop/Esent/suppressions.cs
Normal file
2921
WelsonJS.Toolkit/EsentInterop/Esent/suppressions.cs
Normal file
File diff suppressed because it is too large
Load Diff
76
WelsonJS.Toolkit/EsentInterop/EsentErrorException.cs
Normal file
76
WelsonJS.Toolkit/EsentInterop/EsentErrorException.cs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EsentErrorException.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for ESENT error exceptions.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class EsentErrorException : EsentException
|
||||
{
|
||||
/// <summary>
|
||||
/// The error code that was encountered.
|
||||
/// </summary>
|
||||
private JET_err errorCode;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the EsentErrorException class.
|
||||
/// </summary>
|
||||
/// <param name="message">The description of the error.</param>
|
||||
/// <param name="err">The error code of the exception.</param>
|
||||
internal EsentErrorException(string message, JET_err err) : base(message)
|
||||
{
|
||||
this.errorCode = err;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the EsentErrorException class. This constructor
|
||||
/// is used to deserialize a serialized exception.
|
||||
/// </summary>
|
||||
/// <param name="info">The data needed to deserialize the object.</param>
|
||||
/// <param name="context">The deserialization context.</param>
|
||||
protected EsentErrorException(SerializationInfo info, StreamingContext context) :
|
||||
base(info, context)
|
||||
{
|
||||
this.errorCode = (JET_err)info.GetInt32("errorCode");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying Esent error for this exception.
|
||||
/// </summary>
|
||||
public JET_err Error
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.errorCode;
|
||||
}
|
||||
}
|
||||
|
||||
#if !MANAGEDESENT_ON_CORECLR // Serialization does not work in Core CLR.
|
||||
/// <summary>When overridden in a derived class, sets the <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with information about the exception.</summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown. </param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination. </param>
|
||||
/// <exception cref="T:System.ArgumentNullException">The <paramref name="info" /> parameter is a null reference (Nothing in Visual Basic). </exception>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
/// <PermissionSet>
|
||||
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="*AllFiles*" PathDiscovery="*AllFiles*" />
|
||||
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="SerializationFormatter" />
|
||||
/// </PermissionSet>
|
||||
public override void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
base.GetObjectData(info, context);
|
||||
if (info != null)
|
||||
{
|
||||
info.AddValue("errorCode", this.errorCode, typeof(int));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
51
WelsonJS.Toolkit/EsentInterop/EsentException.cs
Normal file
51
WelsonJS.Toolkit/EsentInterop/EsentException.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EsentException.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
#if !MANAGEDESENT_SUPPORTS_SERIALIZATION && MANAGEDESENT_ON_WSA
|
||||
using Microsoft.Isam.Esent.Interop;
|
||||
using SerializableAttribute = Microsoft.Isam.Esent.Interop.SerializableAttribute;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Base class for ESENT exceptions.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public abstract class EsentException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the EsentException class.
|
||||
/// </summary>
|
||||
protected EsentException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the EsentException class with a specified error message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
protected EsentException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the EsentException class. This constructor
|
||||
/// is used to deserialize a serialized exception.
|
||||
/// </summary>
|
||||
/// <param name="info">The data needed to deserialize the object.</param>
|
||||
/// <param name="context">The deserialization context.</param>
|
||||
protected EsentException(SerializationInfo info, StreamingContext context)
|
||||
#if MANAGEDESENT_SUPPORTS_SERIALIZATION || !MANAGEDESENT_ON_WSA
|
||||
: base(info, context)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
109
WelsonJS.Toolkit/EsentInterop/EsentInterop.csproj
Normal file
109
WelsonJS.Toolkit/EsentInterop/EsentInterop.csproj
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{E929E163-52A0-4AAC-917B-6D7FAF70C45E}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Esent.Interop</RootNamespace>
|
||||
<AssemblyName>Esent.Interop</AssemblyName>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<DefineConstants></DefineConstants>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<PublicKeyFile>..\scripts\internal\35MSSharedLib1024.snk</PublicKeyFile>
|
||||
<Platforms>AnyCPU;x86</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- The .snk file won't be published to codeplex. -->
|
||||
<PropertyGroup Condition="Exists('$(PublicKeyFile)')">
|
||||
<DefineConstants>$(DefineConstants);STRONG_NAMED</DefineConstants>
|
||||
<DelaySign>true</DelaySign>
|
||||
<AssemblyOriginatorKeyFile>$(PublicKeyFile)</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>$(DefineConstants);DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>$(DefineConstants);DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>$(DefineConstants)</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>$(DefineConstants)</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="*.cs" />
|
||||
<Compile Include="Esent\CallbackDataConverter.cs" />
|
||||
<Compile Include="Esent\EsentJetApi.cs" />
|
||||
<Compile Include="Esent\EsentNativeMethods.cs" />
|
||||
<Compile Include="Esent\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
50
WelsonJS.Toolkit/EsentInterop/EsentInvalidColumnException.cs
Normal file
50
WelsonJS.Toolkit/EsentInterop/EsentInvalidColumnException.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EsentInvalidColumnException.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
/// <summary>
|
||||
/// Exception thrown when a column conversion fails.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class EsentInvalidColumnException : EsentException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the EsentInvalidColumnException class.
|
||||
/// </summary>
|
||||
public EsentInvalidColumnException()
|
||||
{
|
||||
}
|
||||
|
||||
#if MANAGEDESENT_ON_CORECLR
|
||||
#else
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the EsentInvalidColumnException class. This constructor
|
||||
/// is used to deserialize a serialized exception.
|
||||
/// </summary>
|
||||
/// <param name="info">The data needed to deserialize the object.</param>
|
||||
/// <param name="context">The deserialization context.</param>
|
||||
protected EsentInvalidColumnException(SerializationInfo info, StreamingContext context) :
|
||||
base(info, context)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets a text message describing the exception.
|
||||
/// </summary>
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Column is not valid for this operation";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
127
WelsonJS.Toolkit/EsentInterop/EsentResource.cs
Normal file
127
WelsonJS.Toolkit/EsentInterop/EsentResource.cs
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EsentResource.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// This is the base class for all esent resource objects.
|
||||
/// Subclasses of this class can allocate and release unmanaged
|
||||
/// resources.
|
||||
/// </summary>
|
||||
public abstract class EsentResource : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// True if a resource has been allocated.
|
||||
/// </summary>
|
||||
private bool hasResource;
|
||||
|
||||
/// <summary>
|
||||
/// True if this object has been disposed.
|
||||
/// </summary>
|
||||
private bool isDisposed;
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the EsentResource class.
|
||||
/// </summary>
|
||||
~EsentResource()
|
||||
{
|
||||
this.Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the underlying resource
|
||||
/// is currently allocated.
|
||||
/// </summary>
|
||||
protected bool HasResource
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.hasResource;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of this object, releasing the underlying
|
||||
/// Esent resource.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by Dispose and the finalizer.
|
||||
/// </summary>
|
||||
/// <param name="isDisposing">
|
||||
/// True if called from Dispose.
|
||||
/// </param>
|
||||
protected virtual void Dispose(bool isDisposing)
|
||||
{
|
||||
if (isDisposing)
|
||||
{
|
||||
if (this.hasResource)
|
||||
{
|
||||
this.ReleaseResource();
|
||||
Debug.Assert(!this.hasResource, "Resource was not freed");
|
||||
}
|
||||
|
||||
this.isDisposed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.hasResource)
|
||||
{
|
||||
// We should not get to this point. The problem is that if
|
||||
// we use finalizers to free esent resources they may end
|
||||
// up being freed in the wrong order (e.g. JetEndSession is
|
||||
// called before JetCloseTable). Freeing esent resources
|
||||
// in the wrong order will generate EsentExceptions.
|
||||
Trace.TraceWarning("Non-finalized ESENT resource {0}", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throw an exception if this object has been disposed.
|
||||
/// </summary>
|
||||
protected void CheckObjectIsNotDisposed()
|
||||
{
|
||||
if (this.isDisposed)
|
||||
{
|
||||
throw new ObjectDisposedException("EsentResource");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by a subclass when a resource is allocated.
|
||||
/// </summary>
|
||||
protected void ResourceWasAllocated()
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
Debug.Assert(!this.hasResource, "Resource is already allocated");
|
||||
this.hasResource = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by a subclass when a resource is freed.
|
||||
/// </summary>
|
||||
protected void ResourceWasReleased()
|
||||
{
|
||||
Debug.Assert(this.hasResource, "Resource is not allocated");
|
||||
this.CheckObjectIsNotDisposed();
|
||||
this.hasResource = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implemented by the subclass to release a resource.
|
||||
/// </summary>
|
||||
protected abstract void ReleaseResource();
|
||||
}
|
||||
}
|
||||
113
WelsonJS.Toolkit/EsentInterop/EsentStopwatch.cs
Normal file
113
WelsonJS.Toolkit/EsentInterop/EsentStopwatch.cs
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EsentStopwatch.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Isam.Esent.Interop.Vista;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a set of methods and properties that you can use to measure
|
||||
/// ESENT work statistics for a thread. If the current version of ESENT
|
||||
/// doesn't support <see cref="VistaApi.JetGetThreadStats"/> then all
|
||||
/// ESENT statistics will be 0.
|
||||
/// </summary>
|
||||
public class EsentStopwatch
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to measure how long statistics are collected for.
|
||||
/// </summary>
|
||||
private Stopwatch stopwatch;
|
||||
|
||||
/// <summary>
|
||||
/// The stats at the start of our collection.
|
||||
/// </summary>
|
||||
private JET_THREADSTATS statsAtStart;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the EsentStopwatch timer is running.
|
||||
/// </summary>
|
||||
public bool IsRunning { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total ESENT work stats measured by the current instance.
|
||||
/// </summary>
|
||||
public JET_THREADSTATS ThreadStats { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total elapsed time measured by the current instance.
|
||||
/// </summary>
|
||||
public TimeSpan Elapsed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new EsentStopwatch instance and starts
|
||||
/// measuring elapsed time.
|
||||
/// </summary>
|
||||
/// <returns>A new, running EsentStopwatch.</returns>
|
||||
public static EsentStopwatch StartNew()
|
||||
{
|
||||
var stopwatch = new EsentStopwatch();
|
||||
stopwatch.Start();
|
||||
return stopwatch;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="Stopwatch"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="Stopwatch"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this.IsRunning ? "EsentStopwatch (running)" : this.Elapsed.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts measuring ESENT work.
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
this.Reset();
|
||||
this.stopwatch = Stopwatch.StartNew();
|
||||
this.IsRunning = true;
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
VistaApi.JetGetThreadStats(out this.statsAtStart);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops measuring ESENT work.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (this.IsRunning)
|
||||
{
|
||||
this.IsRunning = false;
|
||||
this.stopwatch.Stop();
|
||||
this.Elapsed = this.stopwatch.Elapsed;
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
JET_THREADSTATS statsAtEnd;
|
||||
VistaApi.JetGetThreadStats(out statsAtEnd);
|
||||
this.ThreadStats = statsAtEnd - this.statsAtStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops time interval measurement and resets the thread statistics.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
this.stopwatch = null;
|
||||
this.ThreadStats = new JET_THREADSTATS();
|
||||
this.Elapsed = TimeSpan.Zero;
|
||||
this.IsRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
134
WelsonJS.Toolkit/EsentInterop/EsentVersion.cs
Normal file
134
WelsonJS.Toolkit/EsentInterop/EsentVersion.cs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="EsentVersion.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using Microsoft.Isam.Esent.Interop.Implementation;
|
||||
|
||||
/// <summary>
|
||||
/// Gives information about the version of esent being used.
|
||||
/// </summary>
|
||||
public static class EsentVersion
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current version of esent
|
||||
/// supports features available in the Windows Server 2003 version of
|
||||
/// esent.
|
||||
/// </summary>
|
||||
public static bool SupportsServer2003Features
|
||||
{
|
||||
get
|
||||
{
|
||||
return Capabilities.SupportsServer2003Features;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current version of esent
|
||||
/// supports features available in the Windows Vista version of
|
||||
/// esent.
|
||||
/// </summary>
|
||||
public static bool SupportsVistaFeatures
|
||||
{
|
||||
get
|
||||
{
|
||||
return Capabilities.SupportsVistaFeatures;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current version of esent
|
||||
/// supports features available in the Windows 7 version of
|
||||
/// esent.
|
||||
/// </summary>
|
||||
public static bool SupportsWindows7Features
|
||||
{
|
||||
get
|
||||
{
|
||||
return Capabilities.SupportsWindows7Features;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current version of esent
|
||||
/// supports features available in the Windows 8 version of
|
||||
/// esent.
|
||||
/// </summary>
|
||||
public static bool SupportsWindows8Features
|
||||
{
|
||||
get
|
||||
{
|
||||
return Capabilities.SupportsWindows8Features;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current version of esent
|
||||
/// supports features available in the Windows 8.1 version of
|
||||
/// esent.
|
||||
/// </summary>
|
||||
public static bool SupportsWindows81Features
|
||||
{
|
||||
get
|
||||
{
|
||||
return Capabilities.SupportsWindows81Features;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current version of esent
|
||||
/// supports features available in the Windows 10 version of
|
||||
/// esent.
|
||||
/// </summary>
|
||||
public static bool SupportsWindows10Features
|
||||
{
|
||||
get
|
||||
{
|
||||
return Capabilities.SupportsWindows10Features;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current version of esent
|
||||
/// can use non-ASCII paths to access databases.
|
||||
/// </summary>
|
||||
public static bool SupportsUnicodePaths
|
||||
{
|
||||
get
|
||||
{
|
||||
return Capabilities.SupportsUnicodePaths;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether large (> 255 byte) keys are supported.
|
||||
/// The key size for an index can be specified in the <see cref="JET_INDEXCREATE"/>
|
||||
/// object.
|
||||
/// </summary>
|
||||
public static bool SupportsLargeKeys
|
||||
{
|
||||
get
|
||||
{
|
||||
return Capabilities.SupportsLargeKeys;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a description of the current Esent capabilities.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We allow this to be set separately so that capabilities can
|
||||
/// be downgraded for testing.
|
||||
/// </remarks>
|
||||
private static JetCapabilities Capabilities
|
||||
{
|
||||
get
|
||||
{
|
||||
return Api.Impl.Capabilities;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
WelsonJS.Toolkit/EsentInterop/FloatColumnValue.cs
Normal file
69
WelsonJS.Toolkit/EsentInterop/FloatColumnValue.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="FloatColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="float"/> column value.
|
||||
/// </summary>
|
||||
public class FloatColumnValue : ColumnValueOfStruct<float>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return sizeof(float); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
var data = this.Value.GetValueOrDefault();
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(float), this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
this.Value = BitConverter.ToSingle(value, startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
94
WelsonJS.Toolkit/EsentInterop/GCHandleCollection.cs
Normal file
94
WelsonJS.Toolkit/EsentInterop/GCHandleCollection.cs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="GCHandleCollection.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Implementation
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
/// <summary>
|
||||
/// A collection of GCHandles for pinned objects. The handles
|
||||
/// are freed when this object is disposed.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
internal struct GCHandleCollection : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The handles of the objects being pinned.
|
||||
/// </summary>
|
||||
private GCHandle[] handles;
|
||||
|
||||
/// <summary>
|
||||
/// Handle count.
|
||||
/// </summary>
|
||||
private int count;
|
||||
|
||||
/// <summary>
|
||||
/// Disposes of the object.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (null != this.handles)
|
||||
{
|
||||
for (int i = 0; i < this.count; i++)
|
||||
{
|
||||
this.handles[i].Free();
|
||||
}
|
||||
|
||||
this.handles = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an object to the handle collection. This automatically
|
||||
/// pins the object.
|
||||
/// </summary>
|
||||
/// <param name="value">The object to pin.</param>
|
||||
/// <returns>
|
||||
/// The address of the pinned object. This is valid until the
|
||||
/// GCHandleCollection is disposed.
|
||||
/// </returns>
|
||||
public IntPtr Add(object value)
|
||||
{
|
||||
if (null == value)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (null == this.handles)
|
||||
{
|
||||
this.handles = new GCHandle[4]; // same as List<T>
|
||||
}
|
||||
else if (this.count == this.handles.Length)
|
||||
{
|
||||
Array.Resize(ref this.handles, this.count * 2);
|
||||
}
|
||||
|
||||
Debug.Assert(this.count < this.handles.Length, "Index out of bound");
|
||||
|
||||
GCHandle handle = GCHandle.Alloc(value, GCHandleType.Pinned);
|
||||
this.handles[this.count++] = handle;
|
||||
|
||||
IntPtr pinned = handle.AddrOfPinnedObject();
|
||||
Debug.Assert(IntPtr.Zero != pinned, "Pinned object has null address");
|
||||
return pinned;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set handle array capacity.
|
||||
/// </summary>
|
||||
/// <param name="capacity">Estimated handle count</param>
|
||||
public void SetCapacity(int capacity)
|
||||
{
|
||||
if (null == this.handles)
|
||||
{
|
||||
this.handles = new GCHandle[capacity];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
64
WelsonJS.Toolkit/EsentInterop/GenericEnumerable.cs
Normal file
64
WelsonJS.Toolkit/EsentInterop/GenericEnumerable.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="GenericEnumerable.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// IEnumerable class that takes a delegate to create the enumerator it returns.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type returned by the enumerator.</typeparam>
|
||||
internal class GenericEnumerable<T> : IEnumerable<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The delegate used to create the enumerator.
|
||||
/// </summary>
|
||||
private readonly CreateEnumerator enumeratorCreator;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GenericEnumerable{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="enumeratorCreator">
|
||||
/// The enumerator creator.
|
||||
/// </param>
|
||||
public GenericEnumerable(CreateEnumerator enumeratorCreator)
|
||||
{
|
||||
this.enumeratorCreator = enumeratorCreator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IEnumerator creating delegate.
|
||||
/// </summary>
|
||||
/// <returns>A new enumerator.</returns>
|
||||
public delegate IEnumerator<T> CreateEnumerator();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through the collection.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/>
|
||||
/// that can be used to iterate through the collection.
|
||||
/// </returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return this.enumeratorCreator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through a collection.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Collections.IEnumerator"/>
|
||||
/// object that can be used to iterate through the collection.
|
||||
/// </returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
48
WelsonJS.Toolkit/EsentInterop/GetLockHelpers.cs
Normal file
48
WelsonJS.Toolkit/EsentInterop/GetLockHelpers.cs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="GetLockHelpers.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Helper methods for JetMakeKey.
|
||||
// </summary>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if !MANAGEDESENT_ON_WSA // Not exposed in MSDK
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// Helper methods for the ESENT API. These wrap JetMakeKey.
|
||||
/// </summary>
|
||||
public static partial class Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Explicitly reserve the ability to update a row, write lock, or to explicitly prevent a row from
|
||||
/// being updated by any other session, read lock. Normally, row write locks are acquired implicitly as a
|
||||
/// result of updating rows. Read locks are usually not required because of record versioning. However,
|
||||
/// in some cases a transaction may desire to explicitly lock a row to enforce serialization, or to ensure
|
||||
/// that a subsequent operation will succeed.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to use. A lock will be acquired on the current record.</param>
|
||||
/// <param name="grbit">Lock options, use this to specify which type of lock to obtain.</param>
|
||||
/// <returns>
|
||||
/// True if the lock was obtained, false otherwise. An exception is thrown if an unexpected
|
||||
/// error is encountered.
|
||||
/// </returns>
|
||||
public static bool TryGetLock(JET_SESID sesid, JET_TABLEID tableid, GetLockGrbit grbit)
|
||||
{
|
||||
var err = (JET_err)Impl.JetGetLock(sesid, tableid, grbit);
|
||||
if (JET_err.WriteConflict == err)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Api.Check((int)err);
|
||||
Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // !MANAGEDESENT_ON_WSA
|
||||
82
WelsonJS.Toolkit/EsentInterop/GuidColumnValue.cs
Normal file
82
WelsonJS.Toolkit/EsentInterop/GuidColumnValue.cs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="GuidColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Guid"/> column value.
|
||||
/// </summary>
|
||||
public class GuidColumnValue : ColumnValueOfStruct<Guid>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return 16; /* sizeof(Guid) */ }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
Guid data = this.Value.GetValueOrDefault();
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, this.Size, this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
unsafe
|
||||
{
|
||||
// There isn't a convenient Guid constructor for this case, so
|
||||
// we copy the data manually.
|
||||
Guid guid;
|
||||
void* guidBuffer = &guid;
|
||||
byte* buffer = (byte*)guidBuffer;
|
||||
for (int i = 0; i < this.Size; ++i)
|
||||
{
|
||||
buffer[i] = value[startIndex + i];
|
||||
}
|
||||
|
||||
this.Value = guid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
26
WelsonJS.Toolkit/EsentInterop/IContentEquatable.cs
Normal file
26
WelsonJS.Toolkit/EsentInterop/IContentEquatable.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="IContentEquatable.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for objects that can have their contents compared against
|
||||
/// each other. This should be used for equality comparisons on mutable
|
||||
/// reference objects where overriding Equals() and GetHashCode() isn't a
|
||||
/// good idea.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of objects to compare.</typeparam>
|
||||
public interface IContentEquatable<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this instance is equal
|
||||
/// to another instance.
|
||||
/// </summary>
|
||||
/// <param name="other">An instance to compare with this instance.</param>
|
||||
/// <returns>True if the two instances are equal.</returns>
|
||||
bool ContentEquals(T other);
|
||||
}
|
||||
}
|
||||
22
WelsonJS.Toolkit/EsentInterop/IDeepCloneable.cs
Normal file
22
WelsonJS.Toolkit/EsentInterop/IDeepCloneable.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="IDeepCloneable.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for objects that can be cloned. This creates a deep copy of
|
||||
/// the object. It is used for cloning meta-data objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object.</typeparam>
|
||||
public interface IDeepCloneable<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a deep copy of the object.
|
||||
/// </summary>
|
||||
/// <returns>A deep copy of the object.</returns>
|
||||
T DeepClone();
|
||||
}
|
||||
}
|
||||
2556
WelsonJS.Toolkit/EsentInterop/IJetApi.cs
Normal file
2556
WelsonJS.Toolkit/EsentInterop/IJetApi.cs
Normal file
File diff suppressed because it is too large
Load Diff
19
WelsonJS.Toolkit/EsentInterop/INullableJetStruct.cs
Normal file
19
WelsonJS.Toolkit/EsentInterop/INullableJetStruct.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="INullableJetStruct.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for Jet structures that are nullable (can have null values).
|
||||
/// </summary>
|
||||
public interface INullableJetStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the structure has a null value.
|
||||
/// </summary>
|
||||
bool HasValue { get; }
|
||||
}
|
||||
}
|
||||
189
WelsonJS.Toolkit/EsentInterop/IndexInfo.cs
Normal file
189
WelsonJS.Toolkit/EsentInterop/IndexInfo.cs
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="IndexInfo.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Information about one esent index. This is not an interop
|
||||
/// class, but is used by the meta-data helper methods.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class IndexInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the index.
|
||||
/// </summary>
|
||||
private readonly string name;
|
||||
|
||||
/// <summary>
|
||||
/// The culture info of the index.
|
||||
/// </summary>
|
||||
private readonly CultureInfo cultureInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Index comparison options.
|
||||
/// </summary>
|
||||
private readonly CompareOptions compareOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Index segments.
|
||||
/// </summary>
|
||||
private readonly ReadOnlyCollection<IndexSegment> indexSegments;
|
||||
|
||||
/// <summary>
|
||||
/// Index options.
|
||||
/// </summary>
|
||||
private readonly CreateIndexGrbit grbit;
|
||||
|
||||
/// <summary>
|
||||
/// Number of unique keys in the index.
|
||||
/// </summary>
|
||||
private readonly int keys;
|
||||
|
||||
/// <summary>
|
||||
/// Number of entries in the index.
|
||||
/// </summary>
|
||||
private readonly int entries;
|
||||
|
||||
/// <summary>
|
||||
/// Number of pages in the index.
|
||||
/// </summary>
|
||||
private readonly int pages;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the IndexInfo class.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the index.</param>
|
||||
/// <param name="cultureInfo">CultureInfo for string sorting.</param>
|
||||
/// <param name="compareOptions">String comparison options.</param>
|
||||
/// <param name="indexSegments">Array of index segment descriptions.</param>
|
||||
/// <param name="grbit">Index options.</param>
|
||||
/// <param name="keys">Number of unique keys in the index.</param>
|
||||
/// <param name="entries">Number of entries in the index.</param>
|
||||
/// <param name="pages">Number of pages in the index.</param>
|
||||
internal IndexInfo(
|
||||
string name,
|
||||
CultureInfo cultureInfo,
|
||||
CompareOptions compareOptions,
|
||||
IndexSegment[] indexSegments,
|
||||
CreateIndexGrbit grbit,
|
||||
int keys,
|
||||
int entries,
|
||||
int pages)
|
||||
{
|
||||
this.name = name;
|
||||
this.cultureInfo = cultureInfo;
|
||||
this.compareOptions = compareOptions;
|
||||
this.indexSegments = new ReadOnlyCollection<IndexSegment>(indexSegments);
|
||||
this.grbit = grbit;
|
||||
this.keys = keys;
|
||||
this.entries = entries;
|
||||
this.pages = pages;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the index.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.name; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the CultureInfo the index is sorted by.
|
||||
/// </summary>
|
||||
public CultureInfo CultureInfo
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.cultureInfo; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the CompareOptions for the index.
|
||||
/// </summary>
|
||||
public CompareOptions CompareOptions
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.compareOptions; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the segments of the index.
|
||||
/// </summary>
|
||||
public IList<IndexSegment> IndexSegments
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.indexSegments; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index options.
|
||||
/// </summary>
|
||||
public CreateIndexGrbit Grbit
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.grbit; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of unique keys in the index.
|
||||
/// This value is not current and is only is updated by Api.JetComputeStats.
|
||||
/// </summary>
|
||||
public int Keys
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.keys; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of entries in the index.
|
||||
/// This value is not current and is only is updated by Api.JetComputeStats.
|
||||
/// </summary>
|
||||
public int Entries
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.entries; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of pages in the index.
|
||||
/// This value is not current and is only is updated by Api.JetComputeStats.
|
||||
/// </summary>
|
||||
public int Pages
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.pages; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="IndexInfo"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="IndexInfo"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append(this.Name);
|
||||
sb.Append(" (");
|
||||
foreach (var segment in this.IndexSegments)
|
||||
{
|
||||
sb.Append(segment.ToString());
|
||||
}
|
||||
|
||||
sb.Append(")");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
153
WelsonJS.Toolkit/EsentInterop/IndexInfoEnumerator.cs
Normal file
153
WelsonJS.Toolkit/EsentInterop/IndexInfoEnumerator.cs
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="IndexInfoEnumerator.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Microsoft.Isam.Esent.Interop.Windows8;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for enumerators that return IndexInfo objects. Subclasses differ
|
||||
/// by how they open the table.
|
||||
/// </summary>
|
||||
internal abstract class IndexInfoEnumerator : TableEnumerator<IndexInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IndexInfoEnumerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="sesid">
|
||||
/// The session to use.
|
||||
/// </param>
|
||||
protected IndexInfoEnumerator(JET_SESID sesid) : base(sesid)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the indexlist used to retrieve data.
|
||||
/// </summary>
|
||||
protected JET_INDEXLIST Indexlist { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entry the cursor is currently positioned on.
|
||||
/// </summary>
|
||||
/// <returns>The entry the cursor is currently positioned on.</returns>
|
||||
protected override IndexInfo GetCurrent()
|
||||
{
|
||||
return this.GetIndexInfoFromIndexlist(this.Sesid, this.Indexlist);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves information about indexes on a table.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="indexname">The name of the index.</param>
|
||||
/// <param name="result">Filled in with information about indexes on the table.</param>
|
||||
/// <param name="infoLevel">The type of information to retrieve.</param>
|
||||
protected abstract void GetIndexInfo(
|
||||
JET_SESID sesid,
|
||||
string indexname,
|
||||
out string result,
|
||||
JET_IdxInfo infoLevel);
|
||||
|
||||
/// <summary>
|
||||
/// Create an array of IndexSegment objects from the data in the current JET_INDEXLIST entry.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="indexlist">The indexlist to take the data from.</param>
|
||||
/// <returns>An array of IndexSegment objects containing the information for the current index.</returns>
|
||||
private static IndexSegment[] GetIndexSegmentsFromIndexlist(JET_SESID sesid, JET_INDEXLIST indexlist)
|
||||
{
|
||||
var numSegments = (int)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidcColumn);
|
||||
Debug.Assert(numSegments > 0, "Index has zero index segments");
|
||||
|
||||
// If we use the wide API (Vista+), then the temp table will be in UTF-16.
|
||||
Encoding encodingOfTextColumns = EsentVersion.SupportsVistaFeatures ? Encoding.Unicode : LibraryHelpers.EncodingASCII;
|
||||
|
||||
var segments = new IndexSegment[numSegments];
|
||||
for (int i = 0; i < numSegments; ++i)
|
||||
{
|
||||
string columnName = Api.RetrieveColumnAsString(
|
||||
sesid,
|
||||
indexlist.tableid,
|
||||
indexlist.columnidcolumnname,
|
||||
encodingOfTextColumns,
|
||||
RetrieveColumnGrbit.None);
|
||||
columnName = StringCache.TryToIntern(columnName);
|
||||
var coltyp = (JET_coltyp)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidcoltyp);
|
||||
var grbit =
|
||||
(IndexKeyGrbit)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidgrbitColumn);
|
||||
bool isAscending = IndexKeyGrbit.Ascending == grbit;
|
||||
var cp = (JET_CP)Api.RetrieveColumnAsInt16(sesid, indexlist.tableid, indexlist.columnidCp);
|
||||
bool isASCII = JET_CP.ASCII == cp;
|
||||
|
||||
segments[i] = new IndexSegment(columnName, coltyp, isAscending, isASCII);
|
||||
|
||||
if (i < numSegments - 1)
|
||||
{
|
||||
Api.JetMove(sesid, indexlist.tableid, JET_Move.Next, MoveGrbit.None);
|
||||
}
|
||||
}
|
||||
|
||||
return segments;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an IndexInfo object from the data in the current JET_INDEXLIST entry.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="indexlist">The indexlist to take the data from.</param>
|
||||
/// <returns>An IndexInfo object containing the information from that record.</returns>
|
||||
private IndexInfo GetIndexInfoFromIndexlist(JET_SESID sesid, JET_INDEXLIST indexlist)
|
||||
{
|
||||
// If we use the wide API (Vista+), then the temp table will be in UTF-16.
|
||||
Encoding encodingOfTextColumns = EsentVersion.SupportsVistaFeatures ? Encoding.Unicode : LibraryHelpers.EncodingASCII;
|
||||
|
||||
string name = Api.RetrieveColumnAsString(
|
||||
sesid, indexlist.tableid, indexlist.columnidindexname, encodingOfTextColumns, RetrieveColumnGrbit.None);
|
||||
name = StringCache.TryToIntern(name);
|
||||
|
||||
CultureInfo cultureInfo = null;
|
||||
|
||||
if (EsentVersion.SupportsWindows8Features)
|
||||
{
|
||||
string localeName;
|
||||
this.GetIndexInfo(sesid, name, out localeName, Windows8IdxInfo.LocaleName);
|
||||
cultureInfo = new CultureInfo(localeName);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if !MANAGEDESENT_ON_CORECLR
|
||||
// This probably won't work on platforms that don't support LCIDs. Newer environments have dropped
|
||||
// LCIDs in favour of locale names. But currently JET_INDEXLIST doesn't expose columnidLocale.
|
||||
int lcid = (int)Api.RetrieveColumnAsInt16(sesid, indexlist.tableid, indexlist.columnidLangid);
|
||||
cultureInfo = LibraryHelpers.CreateCultureInfoByLcid(lcid);
|
||||
#endif // !MANAGEDESENT_ON_CORECLR
|
||||
}
|
||||
|
||||
uint lcmapFlags = (uint)Api.RetrieveColumnAsUInt32(sesid, indexlist.tableid, indexlist.columnidLCMapFlags);
|
||||
CompareOptions compareOptions = Conversions.CompareOptionsFromLCMapFlags(lcmapFlags);
|
||||
uint grbit = (uint)Api.RetrieveColumnAsUInt32(sesid, indexlist.tableid, indexlist.columnidgrbitIndex);
|
||||
|
||||
int keys = (int)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidcKey);
|
||||
int entries = (int)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidcEntry);
|
||||
int pages = (int)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidcPage);
|
||||
|
||||
IndexSegment[] segments = GetIndexSegmentsFromIndexlist(sesid, indexlist);
|
||||
|
||||
return new IndexInfo(
|
||||
name,
|
||||
cultureInfo,
|
||||
compareOptions,
|
||||
segments,
|
||||
(CreateIndexGrbit)grbit,
|
||||
keys,
|
||||
entries,
|
||||
pages);
|
||||
}
|
||||
}
|
||||
}
|
||||
152
WelsonJS.Toolkit/EsentInterop/IndexSegment.cs
Normal file
152
WelsonJS.Toolkit/EsentInterop/IndexSegment.cs
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="IndexSegment.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
/// <summary>
|
||||
/// Describes one segment of an index.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class IndexSegment : IEquatable<IndexSegment>
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the column.
|
||||
/// </summary>
|
||||
private readonly string columnName;
|
||||
|
||||
/// <summary>
|
||||
/// The type of the column.
|
||||
/// </summary>
|
||||
private readonly JET_coltyp coltyp;
|
||||
|
||||
/// <summary>
|
||||
/// True if the column is sorted in ascending order.
|
||||
/// </summary>
|
||||
private readonly bool isAscending;
|
||||
|
||||
/// <summary>
|
||||
/// True if the column is an ASCII column.
|
||||
/// </summary>
|
||||
private readonly bool isASCII;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the IndexSegment class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the indexed column.</param>
|
||||
/// <param name="coltyp">The type of the column.</param>
|
||||
/// <param name="isAscending">True if the column is ascending.</param>
|
||||
/// <param name="isASCII">True if the column is over an ASCII column.</param>
|
||||
internal IndexSegment(
|
||||
string name,
|
||||
JET_coltyp coltyp,
|
||||
bool isAscending,
|
||||
bool isASCII)
|
||||
{
|
||||
this.columnName = name;
|
||||
this.coltyp = coltyp;
|
||||
this.isAscending = isAscending;
|
||||
this.isASCII = isASCII;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets name of the column being indexed.
|
||||
/// </summary>
|
||||
public string ColumnName
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.columnName; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the column being indexed.
|
||||
/// </summary>
|
||||
public JET_coltyp Coltyp
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.coltyp; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the index segment is ascending.
|
||||
/// </summary>
|
||||
public bool IsAscending
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.isAscending; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the index segment is over an ASCII text
|
||||
/// column. This value is only meaningful for text column segments.
|
||||
/// </summary>
|
||||
public bool IsASCII
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.isASCII; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this instance is equal
|
||||
/// to another instance.
|
||||
/// </summary>
|
||||
/// <param name="obj">An object to compare with this instance.</param>
|
||||
/// <returns>True if the two instances are equal.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null || this.GetType() != obj.GetType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.Equals((IndexSegment)obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a string representation of the instance.
|
||||
/// </summary>
|
||||
/// <returns>The structure as a string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture, "{0}{1}({2})", this.isAscending ? "+" : "-", this.columnName, this.coltyp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>The hash code for this instance.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.columnName.GetHashCode()
|
||||
^ (int)this.coltyp * 31
|
||||
^ (this.isAscending ? 0x10000 : 0x20000)
|
||||
^ (this.isASCII ? 0x40000 : 0x80000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether this instance is equal
|
||||
/// to another instance.
|
||||
/// </summary>
|
||||
/// <param name="other">An instance to compare with this instance.</param>
|
||||
/// <returns>True if the two instances are equal.</returns>
|
||||
public bool Equals(IndexSegment other)
|
||||
{
|
||||
if (null == other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.columnName.Equals(other.columnName, StringComparison.OrdinalIgnoreCase)
|
||||
&& this.coltyp == other.coltyp
|
||||
&& this.isAscending == other.isAscending
|
||||
&& this.isASCII == other.isASCII;
|
||||
}
|
||||
}
|
||||
}
|
||||
337
WelsonJS.Toolkit/EsentInterop/Instance.cs
Normal file
337
WelsonJS.Toolkit/EsentInterop/Instance.cs
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Instance.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Permissions;
|
||||
|
||||
using Microsoft.Isam.Esent.Interop.Vista;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
/// <summary>
|
||||
/// A class that encapsulates a <see cref="JET_INSTANCE"/> in a disposable object. The
|
||||
/// instance must be closed last and closing the instance releases all other
|
||||
/// resources for the instance.
|
||||
/// </summary>
|
||||
public class Instance : SafeHandleZeroOrMinusOneIsInvalid
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters for the instance.
|
||||
/// </summary>
|
||||
private readonly InstanceParameters parameters;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the instance.
|
||||
/// </summary>
|
||||
private readonly string name;
|
||||
|
||||
/// <summary>
|
||||
/// The display name of the instance.
|
||||
/// </summary>
|
||||
private readonly string displayName;
|
||||
|
||||
/// <summary>
|
||||
/// The TermGrbit to be used at JetTerm time.
|
||||
/// </summary>
|
||||
private TermGrbit termGrbit;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Instance class. The underlying
|
||||
/// JET_INSTANCE is allocated, but not initialized.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// The name of the instance. This string must be unique within a
|
||||
/// given process hosting the database engine.
|
||||
/// </param>
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
public Instance(string name) : this(name, name, TermGrbit.None)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Instance class. The underlying
|
||||
/// JET_INSTANCE is allocated, but not initialized.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// The name of the instance. This string must be unique within a
|
||||
/// given process hosting the database engine.
|
||||
/// </param>
|
||||
/// <param name="displayName">
|
||||
/// A display name for the instance. This will be used in eventlog
|
||||
/// entries.
|
||||
/// </param>
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
public Instance(string name, string displayName) : this(name, displayName, TermGrbit.None)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Instance class. The underlying
|
||||
/// JET_INSTANCE is allocated, but not initialized.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// The name of the instance. This string must be unique within a
|
||||
/// given process hosting the database engine.
|
||||
/// </param>
|
||||
/// <param name="displayName">
|
||||
/// A display name for the instance. This will be used in eventlog
|
||||
/// entries.
|
||||
/// </param>
|
||||
/// <param name="termGrbit">
|
||||
/// The TermGrbit to be used at JetTerm time.
|
||||
/// </param>
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
public Instance(string name, string displayName, TermGrbit termGrbit) : base(true)
|
||||
{
|
||||
this.name = name;
|
||||
this.displayName = displayName;
|
||||
this.termGrbit = termGrbit;
|
||||
|
||||
JET_INSTANCE instance;
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
this.SetHandle(JET_INSTANCE.Nil.Value);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// This is the code that we want in a constrained execution region.
|
||||
// We need to avoid the situation where JetCreateInstance2 is called
|
||||
// but the handle isn't set, so the instance is never terminated.
|
||||
// This would happen, for example, if there was a ThreadAbortException
|
||||
// between the call to JetCreateInstance2 and the call to SetHandle.
|
||||
//
|
||||
// If an Esent exception is generated we do not want to call SetHandle
|
||||
// because the instance isn't valid. On the other hand if a different
|
||||
// exception (out of memory or thread abort) is generated we still need
|
||||
// to set the handle to avoid losing track of the instance. The call to
|
||||
// JetCreateInstance2 is in the CER to make sure that the only exceptions
|
||||
// which can be generated are from ESENT failures.
|
||||
Api.JetCreateInstance2(out instance, this.name, this.displayName, CreateInstanceGrbit.None);
|
||||
this.SetHandle(instance.Value);
|
||||
}
|
||||
|
||||
this.parameters = new InstanceParameters(instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the JET_INSTANCE that this instance contains.
|
||||
/// </summary>
|
||||
public JET_INSTANCE JetInstance
|
||||
{
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
get
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
return this.CreateInstanceFromHandle();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the InstanceParameters for this instance.
|
||||
/// </summary>
|
||||
public InstanceParameters Parameters
|
||||
{
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
get
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
return this.parameters;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the TermGrbit for this instance.
|
||||
/// </summary>
|
||||
public TermGrbit TermGrbit
|
||||
{
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
get
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
return this.termGrbit;
|
||||
}
|
||||
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
set
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
this.termGrbit = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provide implicit conversion of an Instance object to a JET_INSTANCE
|
||||
/// structure. This is done so that an Instance can be used anywhere a
|
||||
/// JET_INSTANCE is required.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance to convert.</param>
|
||||
/// <returns>The JET_INSTANCE wrapped by the instance.</returns>
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
public static implicit operator JET_INSTANCE(Instance instance)
|
||||
{
|
||||
return instance.JetInstance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="Instance"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="Instance"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0} ({1})", this.displayName, this.name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the JET_INSTANCE.
|
||||
/// </summary>
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
public void Init()
|
||||
{
|
||||
this.Init(InitGrbit.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the JET_INSTANCE.
|
||||
/// </summary>
|
||||
/// <param name="grbit">
|
||||
/// Initialization options.
|
||||
/// </param>
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
public void Init(InitGrbit grbit)
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
JET_INSTANCE instance = this.JetInstance;
|
||||
|
||||
// Use a constrained region so that the handle is
|
||||
// always set after JetInit2 is called.
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
// Remember that a failure in JetInit can zero the handle
|
||||
// and that JetTerm should not be called in that case.
|
||||
Api.JetInit2(ref instance, grbit);
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.SetHandle(instance.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the JET_INSTANCE. This API requires at least the
|
||||
/// Vista version of ESENT.
|
||||
/// </summary>
|
||||
/// <param name="recoveryOptions">
|
||||
/// Additional recovery parameters for remapping databases during
|
||||
/// recovery, position where to stop recovery at, or recovery status.
|
||||
/// </param>
|
||||
/// <param name="grbit">
|
||||
/// Initialization options.
|
||||
/// </param>
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
public void Init(JET_RSTINFO recoveryOptions, InitGrbit grbit)
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
JET_INSTANCE instance = this.JetInstance;
|
||||
|
||||
// Use a constrained region so that the handle is
|
||||
// always set after JetInit3 is called.
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
// Remember that a failure in JetInit can zero the handle
|
||||
// and that JetTerm should not be called in that case.
|
||||
VistaApi.JetInit3(ref instance, recoveryOptions, grbit);
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.SetHandle(instance.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Terminate the JET_INSTANCE.
|
||||
/// </summary>
|
||||
[SuppressMessage(
|
||||
"Microsoft.StyleCop.CSharp.MaintainabilityRules",
|
||||
"SA1409:RemoveUnnecessaryCode",
|
||||
Justification = "CER code belongs in the finally block, so the try clause is empty")]
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
public void Term()
|
||||
{
|
||||
// Use a constrained region so that the handle is
|
||||
// always set as invalid after JetTerm is called.
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
// This try block deliberately left blank.
|
||||
}
|
||||
finally
|
||||
{
|
||||
// This is the code that we want in a constrained execution region.
|
||||
// We need to avoid the situation where JetTerm is called
|
||||
// but the handle isn't invalidated, so the instance is terminated again.
|
||||
// This would happen, for example, if there was a ThreadAbortException
|
||||
// between the call to JetTerm and the call to SetHandle.
|
||||
//
|
||||
// If an Esent exception is generated we do not want to invalidate the handle
|
||||
// because the instance isn't necessarily terminated. On the other hand if a
|
||||
// different exception (out of memory or thread abort) is generated we still need
|
||||
// to invalidate the handle.
|
||||
try
|
||||
{
|
||||
Api.JetTerm2(this.JetInstance, this.termGrbit);
|
||||
}
|
||||
catch (EsentDirtyShutdownException)
|
||||
{
|
||||
this.SetHandleAsInvalid();
|
||||
throw;
|
||||
}
|
||||
|
||||
this.SetHandleAsInvalid();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release the handle for this instance.
|
||||
/// </summary>
|
||||
/// <returns>True if the handle could be released.</returns>
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
// The object is already marked as invalid so don't check
|
||||
var instance = this.CreateInstanceFromHandle();
|
||||
return (int)JET_err.Success == Api.Impl.JetTerm2(instance, this.termGrbit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a JET_INSTANCE from the internal handle value.
|
||||
/// </summary>
|
||||
/// <returns>A JET_INSTANCE containing the internal handle.</returns>
|
||||
private JET_INSTANCE CreateInstanceFromHandle()
|
||||
{
|
||||
return new JET_INSTANCE { Value = this.handle };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check to see if this instance is invalid or closed.
|
||||
/// </summary>
|
||||
[SecurityPermissionAttribute(SecurityAction.LinkDemand)]
|
||||
private void CheckObjectIsNotDisposed()
|
||||
{
|
||||
if (this.IsInvalid || this.IsClosed)
|
||||
{
|
||||
throw new ObjectDisposedException("Instance");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
762
WelsonJS.Toolkit/EsentInterop/InstanceParameters.cs
Normal file
762
WelsonJS.Toolkit/EsentInterop/InstanceParameters.cs
Normal file
|
|
@ -0,0 +1,762 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="InstanceParameters.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using Microsoft.Isam.Esent.Interop.Server2003;
|
||||
using Microsoft.Isam.Esent.Interop.Vista;
|
||||
using Microsoft.Isam.Esent.Interop.Windows7;
|
||||
|
||||
/// <summary>
|
||||
/// This class provides properties to set and get system parameters
|
||||
/// on an ESENT instance.
|
||||
/// </summary>
|
||||
public partial class InstanceParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// The instance to set parameters on.
|
||||
/// </summary>
|
||||
private readonly JET_INSTANCE instance;
|
||||
|
||||
/// <summary>
|
||||
/// The session to set parameters with.
|
||||
/// </summary>
|
||||
private readonly JET_SESID sesid;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the InstanceParameters class.
|
||||
/// </summary>
|
||||
/// <param name="instance">
|
||||
/// The instance to set parameters on. If this is JET_INSTANCE.Nil,
|
||||
/// then the settings affect the default settings of future instances.
|
||||
/// </param>
|
||||
public InstanceParameters(JET_INSTANCE instance)
|
||||
{
|
||||
this.instance = instance;
|
||||
this.sesid = JET_SESID.Nil;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the relative or absolute file system path of the
|
||||
/// folder that will contain the checkpoint file for the instance.
|
||||
/// </summary>
|
||||
public string SystemDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
return Util.AddTrailingDirectorySeparator(this.GetStringParameter(JET_param.SystemPath));
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetStringParameter(JET_param.SystemPath, Util.AddTrailingDirectorySeparator(value));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the relative or absolute file system path of
|
||||
/// the folder that will contain the temporary database for the instance.
|
||||
/// </summary>
|
||||
public string TempDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
// Older versions of Esent (e.g. Windows XP) will return the
|
||||
// full path of the temporary database. Extract the directory name.
|
||||
string path = this.GetStringParameter(JET_param.TempPath);
|
||||
string dir = Path.GetDirectoryName(path);
|
||||
return Util.AddTrailingDirectorySeparator(dir);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetStringParameter(JET_param.TempPath, Util.AddTrailingDirectorySeparator(value));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the relative or absolute file system path of the
|
||||
/// folder that will contain the transaction logs for the instance.
|
||||
/// </summary>
|
||||
public string LogFileDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
return Util.AddTrailingDirectorySeparator(this.GetStringParameter(JET_param.LogFilePath));
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetStringParameter(JET_param.LogFilePath, Util.AddTrailingDirectorySeparator(value));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the relative or absolute file system path of the
|
||||
/// a folder where crash recovery or a restore operation can find
|
||||
/// the databases referenced in the transaction log in the
|
||||
/// specified folder.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This parameter is ignored on Windows XP.
|
||||
/// </remarks>
|
||||
public string AlternateDatabaseRecoveryDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EsentVersion.SupportsServer2003Features)
|
||||
{
|
||||
return
|
||||
Util.AddTrailingDirectorySeparator(
|
||||
this.GetStringParameter(Server2003Param.AlternateDatabaseRecoveryPath));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (EsentVersion.SupportsServer2003Features)
|
||||
{
|
||||
this.SetStringParameter(
|
||||
Server2003Param.AlternateDatabaseRecoveryPath, Util.AddTrailingDirectorySeparator(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the three letter prefix used for many of the files used by
|
||||
/// the database engine. For example, the checkpoint file is called EDB.CHK by
|
||||
/// default because EDB is the default base name.
|
||||
/// </summary>
|
||||
public string BaseName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetStringParameter(JET_param.BaseName);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetStringParameter(JET_param.BaseName, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an application specific string that will be added to
|
||||
/// any event log messages that are emitted by the database engine. This allows
|
||||
/// easy correlation of event log messages with the source application. By default
|
||||
/// the host application executable name will be used.
|
||||
/// </summary>
|
||||
public string EventSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetStringParameter(JET_param.EventSource);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetStringParameter(JET_param.EventSource, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of sessions resources reserved for this instance.
|
||||
/// A session resource directly corresponds to a JET_SESID.
|
||||
/// </summary>
|
||||
public int MaxSessions
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.MaxSessions);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.MaxSessions, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of B+ Tree resources reserved for this instance.
|
||||
/// </summary>
|
||||
public int MaxOpenTables
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.MaxOpenTables);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.MaxOpenTables, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of cursor resources reserved for this instance.
|
||||
/// A cursor resource directly corresponds to a JET_TABLEID.
|
||||
/// </summary>
|
||||
public int MaxCursors
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.MaxCursors);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.MaxCursors, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum number of version store pages reserved
|
||||
/// for this instance.
|
||||
/// </summary>
|
||||
public int MaxVerPages
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.MaxVerPages);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.MaxVerPages, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the preferred number of version store pages reserved
|
||||
/// for this instance. If the size of the version store exceeds this
|
||||
/// threshold then any information that is only used for optional
|
||||
/// background tasks, such as reclaiming deleted space in the database,
|
||||
/// is instead sacrificed to preserve room for transactional information.
|
||||
/// </summary>
|
||||
public int PreferredVerPages
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.PreferredVerPages);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.PreferredVerPages, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the the number of background cleanup work items that
|
||||
/// can be queued to the database engine thread pool at any one time.
|
||||
/// </summary>
|
||||
public int VersionStoreTaskQueueMax
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.VersionStoreTaskQueueMax);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.VersionStoreTaskQueueMax, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of temporary table resources for use
|
||||
/// by an instance. This setting will affect how many temporary tables can be used at
|
||||
/// the same time. If this system parameter is set to zero then no temporary database
|
||||
/// will be created and any activity that requires use of the temporary database will
|
||||
/// fail. This setting can be useful to avoid the I/O required to create the temporary
|
||||
/// database if it is known that it will not be used.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The use of a temporary table also requires a cursor resource.
|
||||
/// </remarks>
|
||||
public int MaxTemporaryTables
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.MaxTemporaryTables);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.MaxTemporaryTables, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the transaction log files. This parameter
|
||||
/// should be set in units of 1024 bytes (e.g. a setting of 2048 will
|
||||
/// give 2MB logfiles).
|
||||
/// </summary>
|
||||
public int LogFileSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.LogFileSize);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.LogFileSize, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the amount of memory used to cache log records
|
||||
/// before they are written to the transaction log file. The unit for this
|
||||
/// parameter is the sector size of the volume that holds the transaction log files.
|
||||
/// The sector size is almost always 512 bytes, so it is safe to assume that size
|
||||
/// for the unit. This parameter has an impact on performance. When the database
|
||||
/// engine is under heavy update load, this buffer can become full very rapidly.
|
||||
/// A larger cache size for the transaction log file is critical for good update
|
||||
/// performance under such a high load condition. The default is known to be too small
|
||||
/// for this case.
|
||||
/// Do not set this parameter to a number of buffers that is larger (in bytes) than
|
||||
/// half the size of a transaction log file.
|
||||
/// </summary>
|
||||
public int LogBuffers
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.LogBuffers);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.LogBuffers, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether circular logging is on.
|
||||
/// When circular logging is off, all transaction log files that are generated
|
||||
/// are retained on disk until they are no longer needed because a full backup of the
|
||||
/// database has been performed. When circular logging is on, only transaction log files
|
||||
/// that are younger than the current checkpoint are retained on disk. The benefit of
|
||||
/// this mode is that backups are not required to retire old transaction log files.
|
||||
/// </summary>
|
||||
public bool CircularLog
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetBoolParameter(JET_param.CircularLog);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetBoolParameter(JET_param.CircularLog, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether JetInit fails when the database
|
||||
/// engine is configured to start using transaction log files on disk
|
||||
/// that are of a different size than what is configured. Normally,
|
||||
/// <see cref="Api.JetInit"/> will successfully recover the databases
|
||||
/// but will fail with <see cref="JET_err.LogFileSizeMismatchDatabasesConsistent"/>
|
||||
/// to indicate that the log file size is misconfigured. However, when
|
||||
/// this parameter is set to true then the database engine will silently
|
||||
/// delete all the old log files, start a new set of transaction log files
|
||||
/// using the configured log file size. This parameter is useful when the
|
||||
/// application wishes to transparently change its transaction log file
|
||||
/// size yet still work transparently in upgrade and restore scenarios.
|
||||
/// </summary>
|
||||
public bool CleanupMismatchedLogFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetBoolParameter(JET_param.CleanupMismatchedLogFiles);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetBoolParameter(JET_param.CleanupMismatchedLogFiles, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the initial size of the temporary database. The size is in
|
||||
/// database pages. A size of zero indicates that the default size of an ordinary
|
||||
/// database should be used. It is often desirable for small applications to configure
|
||||
/// the temporary database to be as small as possible. Setting this parameter to
|
||||
/// <see cref="SystemParameters.PageTempDBSmallest"/> will achieve the smallest
|
||||
/// temporary database possible.
|
||||
/// </summary>
|
||||
public int PageTempDBMin
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.PageTempDBMin);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.PageTempDBMin, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the threshold in bytes for about how many transaction log
|
||||
/// files will need to be replayed after a crash. If circular logging is enabled using
|
||||
/// CircularLog then this parameter will also control the approximate amount
|
||||
/// of transaction log files that will be retained on disk.
|
||||
/// </summary>
|
||||
public int CheckpointDepthMax
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.CheckpointDepthMax);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.CheckpointDepthMax, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of pages that are added to a database file each
|
||||
/// time it needs to grow to accommodate more data.
|
||||
/// </summary>
|
||||
public int DbExtensionSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetIntegerParameter(JET_param.DbExtensionSize);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.DbExtensionSize, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether crash recovery is on.
|
||||
/// </summary>
|
||||
public bool Recovery
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0 == string.Compare(this.GetStringParameter(JET_param.Recovery), "on", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
this.SetStringParameter(JET_param.Recovery, "on");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.SetStringParameter(JET_param.Recovery, "off");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether online defragmentation is enabled.
|
||||
/// </summary>
|
||||
public bool EnableOnlineDefrag
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetBoolParameter(JET_param.EnableOnlineDefrag);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetBoolParameter(JET_param.EnableOnlineDefrag, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether <see cref="Api.JetAttachDatabase"/> will check for
|
||||
/// indexes that were build using an older version of the NLS library in the
|
||||
/// operating system.
|
||||
/// </summary>
|
||||
public bool EnableIndexChecking
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetBoolParameter(JET_param.EnableIndexChecking);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetBoolParameter(JET_param.EnableIndexChecking, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the event log the database engine uses for its event log
|
||||
/// messages. By default, all event log messages will go to the Application event log. If the registry
|
||||
/// key name for another event log is configured then the event log messages will go there instead.
|
||||
/// </summary>
|
||||
public string EventSourceKey
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetStringParameter(JET_param.EventSourceKey);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetStringParameter(JET_param.EventSourceKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether informational event
|
||||
/// log messages that would ordinarily be generated by the
|
||||
/// database engine will be suppressed.
|
||||
/// </summary>
|
||||
public bool NoInformationEvent
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetBoolParameter(JET_param.NoInformationEvent);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetBoolParameter(JET_param.NoInformationEvent, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the detail level of eventlog messages that are emitted
|
||||
/// to the eventlog by the database engine. Higher numbers will result
|
||||
/// in more detailed eventlog messages.
|
||||
/// </summary>
|
||||
public EventLoggingLevels EventLoggingLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
return (EventLoggingLevels)this.GetIntegerParameter(JET_param.EventLoggingLevel);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetIntegerParameter(JET_param.EventLoggingLevel, (int)value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether only one database is allowed to
|
||||
/// be opened using JetOpenDatabase by a given session at one time.
|
||||
/// The temporary database is excluded from this restriction.
|
||||
/// </summary>
|
||||
public bool OneDatabasePerSession
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetBoolParameter(JET_param.OneDatabasePerSession);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetBoolParameter(JET_param.OneDatabasePerSession, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether ESENT will silently create folders
|
||||
/// that are missing in its filesystem paths.
|
||||
/// </summary>
|
||||
public bool CreatePathIfNotExist
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetBoolParameter(JET_param.CreatePathIfNotExist);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetBoolParameter(JET_param.CreatePathIfNotExist, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value giving the number of B+ Tree resources cached by
|
||||
/// the instance after the tables they represent have been closed by
|
||||
/// the application. Large values for this parameter will cause the
|
||||
/// database engine to use more memory but will increase the speed
|
||||
/// with which a large number of tables can be opened randomly by
|
||||
/// the application. This is useful for applications that have a
|
||||
/// schema with a very large number of tables.
|
||||
/// <para>
|
||||
/// Supported on Windows Vista and up. Ignored on Windows XP and
|
||||
/// Windows Server 2003.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public int CachedClosedTables
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
return this.GetIntegerParameter(VistaParam.CachedClosedTables);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
this.SetIntegerParameter(VistaParam.CachedClosedTables, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a the number of logs that esent will defer database
|
||||
/// flushes for. This can be used to increase database recoverability if
|
||||
/// failures cause logfiles to be lost.
|
||||
/// <para>
|
||||
/// Supported on Windows 7 and up. Ignored on Windows XP,
|
||||
/// Windows Server 2003, Windows Vista and Windows Server 2008.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public int WaypointLatency
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EsentVersion.SupportsWindows7Features)
|
||||
{
|
||||
return this.GetIntegerParameter(Windows7Param.WaypointLatency);
|
||||
}
|
||||
|
||||
// older versions have no waypoint
|
||||
return 0;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (EsentVersion.SupportsWindows7Features)
|
||||
{
|
||||
this.SetIntegerParameter(Windows7Param.WaypointLatency, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether <see cref="Api.JetAttachDatabase"/> will
|
||||
/// delete indexes that were build using an older version of the NLS library in the
|
||||
/// operating system.
|
||||
/// </summary>
|
||||
public bool EnableIndexCleanup
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetBoolParameter(JET_param.EnableIndexCleanup);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.SetBoolParameter(JET_param.EnableIndexCleanup, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="InstanceParameters"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="InstanceParameters"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "InstanceParameters (0x{0:x})", this.instance.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a system parameter which is a string.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to set.</param>
|
||||
/// <param name="value">The value to set.</param>
|
||||
private void SetStringParameter(JET_param param, string value)
|
||||
{
|
||||
Api.JetSetSystemParameter(this.instance, this.sesid, param, 0, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a system parameter which is a string.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to get.</param>
|
||||
/// <returns>The value of the parameter.</returns>
|
||||
private string GetStringParameter(JET_param param)
|
||||
{
|
||||
int ignored = 0;
|
||||
string value;
|
||||
Api.JetGetSystemParameter(this.instance, this.sesid, param, ref ignored, out value, 1024);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a system parameter which is an integer.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to set.</param>
|
||||
/// <param name="value">The value to set.</param>
|
||||
private void SetIntegerParameter(JET_param param, int value)
|
||||
{
|
||||
Api.JetSetSystemParameter(this.instance, this.sesid, param, value, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a system parameter which is an integer.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to get.</param>
|
||||
/// <returns>The value of the parameter.</returns>
|
||||
private int GetIntegerParameter(JET_param param)
|
||||
{
|
||||
int value = 0;
|
||||
string ignored;
|
||||
Api.JetGetSystemParameter(this.instance, this.sesid, param, ref value, out ignored, 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a system parameter which is a boolean.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to set.</param>
|
||||
/// <param name="value">The value to set.</param>
|
||||
private void SetBoolParameter(JET_param param, bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
Api.JetSetSystemParameter(this.instance, this.sesid, param, 1, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
Api.JetSetSystemParameter(this.instance, this.sesid, param, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a system parameter which is a boolean.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to get.</param>
|
||||
/// <returns>The value of the parameter.</returns>
|
||||
private bool GetBoolParameter(JET_param param)
|
||||
{
|
||||
int value = 0;
|
||||
string ignored;
|
||||
Api.JetGetSystemParameter(this.instance, this.sesid, param, ref value, out ignored, 0);
|
||||
return value != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
WelsonJS.Toolkit/EsentInterop/Int16ColumnValue.cs
Normal file
69
WelsonJS.Toolkit/EsentInterop/Int16ColumnValue.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Int16ColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="short"/> column value.
|
||||
/// </summary>
|
||||
public class Int16ColumnValue : ColumnValueOfStruct<short>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return sizeof(short); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
var data = this.Value.GetValueOrDefault();
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(short), this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
this.Value = BitConverter.ToInt16(value, startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
WelsonJS.Toolkit/EsentInterop/Int32ColumnValue.cs
Normal file
69
WelsonJS.Toolkit/EsentInterop/Int32ColumnValue.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Int32ColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="int"/> column value.
|
||||
/// </summary>
|
||||
public class Int32ColumnValue : ColumnValueOfStruct<int>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return sizeof(int); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
var data = this.Value.GetValueOrDefault();
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(int), this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
this.Value = BitConverter.ToInt32(value, startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
WelsonJS.Toolkit/EsentInterop/Int64ColumnValue.cs
Normal file
69
WelsonJS.Toolkit/EsentInterop/Int64ColumnValue.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Int64ColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="long"/> column value.
|
||||
/// </summary>
|
||||
public class Int64ColumnValue : ColumnValueOfStruct<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return sizeof(long); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
var data = this.Value.GetValueOrDefault();
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(long), this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
this.Value = BitConverter.ToInt64(value, startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
192
WelsonJS.Toolkit/EsentInterop/InternalApi.cs
Normal file
192
WelsonJS.Toolkit/EsentInterop/InternalApi.cs
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="InternalApi.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Internal-only methods of the Api.
|
||||
/// </summary>
|
||||
public static partial class Api
|
||||
{
|
||||
/// <summary>
|
||||
/// The JetSetColumn function modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record. It can overwrite an existing value, add a new value to a sequence of
|
||||
/// values in a multi-valued column, remove a value from a sequence of values in a multi-valued column,
|
||||
/// or update all or part of a long value (a column of type <see cref="JET_coltyp.LongText"/>
|
||||
/// or <see cref="JET_coltyp.LongBinary"/>).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is an internal-only version of the API that takes a data buffer and an offset into the buffer.
|
||||
/// </remarks>
|
||||
/// <param name="sesid">The session which is performing the update.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
/// <param name="dataSize">The size of data to set.</param>
|
||||
/// <param name="dataOffset">The offset in the data buffer to set data from.</param>
|
||||
/// <param name="grbit">SetColumn options.</param>
|
||||
/// <param name="setinfo">Used to specify itag or long-value offset.</param>
|
||||
/// <returns>A warning value.</returns>
|
||||
public static JET_wrn JetSetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, int dataSize, int dataOffset, SetColumnGrbit grbit, JET_SETINFO setinfo)
|
||||
{
|
||||
if (dataOffset < 0
|
||||
|| (null != data && 0 != dataSize && dataOffset >= data.Length)
|
||||
|| (null == data && dataOffset != 0))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
"dataOffset",
|
||||
dataOffset,
|
||||
"must be inside the data buffer");
|
||||
}
|
||||
|
||||
if (null != data && dataSize > checked(data.Length - dataOffset) && (SetColumnGrbit.SizeLV != (grbit & SetColumnGrbit.SizeLV)))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
"dataSize",
|
||||
dataSize,
|
||||
"cannot be greater than the length of the data (unless the SizeLV option is used)");
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* pointer = data)
|
||||
{
|
||||
return Api.JetSetColumn(sesid, tableid, columnid, new IntPtr(pointer + dataOffset), dataSize, grbit, setinfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a single column value from the current record. The record is that
|
||||
/// record associated with the index entry at the current position of the cursor.
|
||||
/// Alternatively, this function can retrieve a column from a record being created
|
||||
/// in the cursor copy buffer. This function can also retrieve column data from an
|
||||
/// index entry that references the current record. In addition to retrieving the
|
||||
/// actual column value, JetRetrieveColumn can also be used to retrieve the size
|
||||
/// of a column, before retrieving the column data itself so that application
|
||||
/// buffers can be sized appropriately.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is an internal method that takes a buffer offset as well as size.
|
||||
/// </remarks>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to retrieve the column from.</param>
|
||||
/// <param name="columnid">The columnid to retrieve.</param>
|
||||
/// <param name="data">The data buffer to be retrieved into.</param>
|
||||
/// <param name="dataSize">The size of the data buffer.</param>
|
||||
/// <param name="dataOffset">Offset into the data buffer to read data into.</param>
|
||||
/// <param name="actualDataSize">Returns the actual size of the data buffer.</param>
|
||||
/// <param name="grbit">Retrieve column options.</param>
|
||||
/// <param name="retinfo">
|
||||
/// If pretinfo is give as NULL then the function behaves as though an itagSequence
|
||||
/// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
|
||||
/// retrieve the first value of a multi-valued column, and to retrieve long data at
|
||||
/// offset 0 (zero).
|
||||
/// </param>
|
||||
/// <returns>An ESENT warning code.</returns>
|
||||
public static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, int dataSize, int dataOffset, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
|
||||
{
|
||||
if (dataOffset < 0
|
||||
|| (null != data && 0 != dataSize && dataOffset >= data.Length)
|
||||
|| (null == data && dataOffset != 0))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
"dataOffset",
|
||||
dataOffset,
|
||||
"must be inside the data buffer");
|
||||
}
|
||||
|
||||
if ((null == data && dataSize > 0) || (null != data && dataSize > data.Length))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
"dataSize",
|
||||
dataSize,
|
||||
"cannot be greater than the length of the data");
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* pointer = data)
|
||||
{
|
||||
return Api.JetRetrieveColumn(
|
||||
sesid, tableid, columnid, new IntPtr(pointer + dataOffset), dataSize, out actualDataSize, grbit, retinfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a single column value from the current record. The record is that
|
||||
/// record associated with the index entry at the current position of the cursor.
|
||||
/// Alternatively, this function can retrieve a column from a record being created
|
||||
/// in the cursor copy buffer. This function can also retrieve column data from an
|
||||
/// index entry that references the current record. In addition to retrieving the
|
||||
/// actual column value, JetRetrieveColumn can also be used to retrieve the size
|
||||
/// of a column, before retrieving the column data itself so that application
|
||||
/// buffers can be sized appropriately.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is an internal-use version that takes an IntPtr.
|
||||
/// </remarks>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to retrieve the column from.</param>
|
||||
/// <param name="columnid">The columnid to retrieve.</param>
|
||||
/// <param name="data">The data buffer to be retrieved into.</param>
|
||||
/// <param name="dataSize">The size of the data buffer.</param>
|
||||
/// <param name="actualDataSize">Returns the actual size of the data buffer.</param>
|
||||
/// <param name="grbit">Retrieve column options.</param>
|
||||
/// <param name="retinfo">
|
||||
/// If pretinfo is give as NULL then the function behaves as though an itagSequence
|
||||
/// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
|
||||
/// retrieve the first value of a multi-valued column, and to retrieve long data at
|
||||
/// offset 0 (zero).
|
||||
/// </param>
|
||||
/// <returns>An ESENT warning code.</returns>
|
||||
internal static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, IntPtr data, int dataSize, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
|
||||
{
|
||||
return Api.Check(Impl.JetRetrieveColumn(sesid, tableid, columnid, data, dataSize, out actualDataSize, grbit, retinfo));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs search keys that may then be used by JetSeek and JetSetIndexRange.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is an internal (unsafe) version that takes an IntPtr.
|
||||
/// </remarks>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="dataSize">Size of the data.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
internal static void JetMakeKey(JET_SESID sesid, JET_TABLEID tableid, IntPtr data, int dataSize, MakeKeyGrbit grbit)
|
||||
{
|
||||
Api.Check(Impl.JetMakeKey(sesid, tableid, data, dataSize, grbit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The JetSetColumn function modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record. It can overwrite an existing value, add a new value to a sequence of
|
||||
/// values in a multi-valued column, remove a value from a sequence of values in a multi-valued column,
|
||||
/// or update all or part of a long value, a column of type JET_coltyp.LongText or JET_coltyp.LongBinary.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method takes an IntPtr and is intended for internal use only.
|
||||
/// </remarks>
|
||||
/// <param name="sesid">The session which is performing the update.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
/// <param name="dataSize">The size of data to set.</param>
|
||||
/// <param name="grbit">SetColumn options.</param>
|
||||
/// <param name="setinfo">Used to specify itag or long-value offset.</param>
|
||||
/// <returns>A warning value.</returns>
|
||||
internal static JET_wrn JetSetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, IntPtr data, int dataSize, SetColumnGrbit grbit, JET_SETINFO setinfo)
|
||||
{
|
||||
return Api.Check(Impl.JetSetColumn(sesid, tableid, columnid, data, dataSize, grbit, setinfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
56
WelsonJS.Toolkit/EsentInterop/IntersectIndexesEnumerator.cs
Normal file
56
WelsonJS.Toolkit/EsentInterop/IntersectIndexesEnumerator.cs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="IntersectIndexesEnumerator.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerator that can intersect indexes and return the intersected bookmarks.
|
||||
/// </summary>
|
||||
internal sealed class IntersectIndexesEnumerator : TableEnumerator<byte[]>
|
||||
{
|
||||
/// <summary>
|
||||
/// The ranges to intersect.
|
||||
/// </summary>
|
||||
private readonly JET_INDEXRANGE[] ranges;
|
||||
|
||||
/// <summary>
|
||||
/// The recordlist containing the result of the intersection.
|
||||
/// </summary>
|
||||
private JET_RECORDLIST recordlist;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IntersectIndexesEnumerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="sesid">
|
||||
/// The session to use.
|
||||
/// </param>
|
||||
/// <param name="ranges">
|
||||
/// The ranges to intersect.
|
||||
/// </param>
|
||||
public IntersectIndexesEnumerator(JET_SESID sesid, JET_INDEXRANGE[] ranges) : base(sesid)
|
||||
{
|
||||
this.ranges = ranges;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open the table to be enumerated. This should set <see cref="TableEnumerator{T}.TableidToEnumerate"/>.
|
||||
/// </summary>
|
||||
protected override void OpenTable()
|
||||
{
|
||||
Api.JetIntersectIndexes(this.Sesid, this.ranges, this.ranges.Length, out this.recordlist, IntersectIndexesGrbit.None);
|
||||
this.TableidToEnumerate = this.recordlist.tableid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entry the cursor is currently positioned on.
|
||||
/// </summary>
|
||||
/// <returns>The entry the cursor is currently positioned on.</returns>
|
||||
protected override byte[] GetCurrent()
|
||||
{
|
||||
return Api.RetrieveColumn(this.Sesid, this.TableidToEnumerate, this.recordlist.columnidBookmark);
|
||||
}
|
||||
}
|
||||
}
|
||||
44
WelsonJS.Toolkit/EsentInterop/JET_eventlogginglevel.cs
Normal file
44
WelsonJS.Toolkit/EsentInterop/JET_eventlogginglevel.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="JET_eventlogginglevel.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for EventLoggingLevel.
|
||||
/// </summary>
|
||||
public enum EventLoggingLevels
|
||||
{
|
||||
/// <summary>
|
||||
/// Disable all events.
|
||||
/// </summary>
|
||||
Disable = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Default level. Windows 7 and later.
|
||||
/// </summary>
|
||||
Min = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Low verbosity and lower. Windows 7 and later.
|
||||
/// </summary>
|
||||
Low = 25,
|
||||
|
||||
/// <summary>
|
||||
/// Medium verbosity and lower. Windows 7 and later.
|
||||
/// </summary>
|
||||
Medium = 50,
|
||||
|
||||
/// <summary>
|
||||
/// High verbosity and lower. Windows 7 and later.
|
||||
/// </summary>
|
||||
High = 75,
|
||||
|
||||
/// <summary>
|
||||
/// All events.
|
||||
/// </summary>
|
||||
Max = 100,
|
||||
}
|
||||
}
|
||||
6451
WelsonJS.Toolkit/EsentInterop/JetApi.cs
Normal file
6451
WelsonJS.Toolkit/EsentInterop/JetApi.cs
Normal file
File diff suppressed because it is too large
Load Diff
175
WelsonJS.Toolkit/EsentInterop/JetCallbackWrapper.cs
Normal file
175
WelsonJS.Toolkit/EsentInterop/JetCallbackWrapper.cs
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="JetCallbackWrapper.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
/// <summary>
|
||||
/// A multi-purpose callback function used by the database engine to inform
|
||||
/// the application of an event involving online defragmentation and cursor
|
||||
/// state notifications.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session for which the callback is being made.</param>
|
||||
/// <param name="dbid">The database for which the callback is being made.</param>
|
||||
/// <param name="tableid">The cursor for which the callback is being made.</param>
|
||||
/// <param name="cbtyp">The operation for which the callback is being made.</param>
|
||||
/// <param name="arg1">First callback-specific argument.</param>
|
||||
/// <param name="arg2">Second callback-specific argument.</param>
|
||||
/// <param name="context">Callback context.</param>
|
||||
/// <param name="unused">This parameter is not used.</param>
|
||||
/// <returns>An ESENT error code.</returns>
|
||||
internal delegate JET_err NATIVE_CALLBACK(
|
||||
IntPtr sesid,
|
||||
uint dbid,
|
||||
IntPtr tableid,
|
||||
uint cbtyp,
|
||||
IntPtr arg1,
|
||||
IntPtr arg2,
|
||||
IntPtr context,
|
||||
IntPtr unused);
|
||||
|
||||
/// <summary>
|
||||
/// Wraps a NATIVE_CALLBACK callback around a JET_CALLBACK. This is
|
||||
/// used to catch exceptions and provide argument conversion.
|
||||
/// </summary>
|
||||
internal sealed class JetCallbackWrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// API call tracing.
|
||||
/// </summary>
|
||||
private static readonly TraceSwitch TraceSwitch = new TraceSwitch("ESENT JetCallbackWrapper", "Wrapper around unmanaged ESENT callback");
|
||||
|
||||
/// <summary>
|
||||
/// The wrapped status callback.
|
||||
/// </summary>
|
||||
private readonly WeakReference wrappedCallback;
|
||||
|
||||
/// <summary>
|
||||
/// The native version of the callback. This will actually be a closure
|
||||
/// because we are calling a non-static method. Keep track of it here
|
||||
/// to make sure that it isn't garbage collected.
|
||||
/// </summary>
|
||||
private readonly NATIVE_CALLBACK nativeCallback;
|
||||
|
||||
#if !MANAGEDESENT_ON_WSA
|
||||
/// <summary>
|
||||
/// Initializes static members of the <see cref="JetCallbackWrapper"/> class.
|
||||
/// </summary>
|
||||
static JetCallbackWrapper()
|
||||
{
|
||||
// We don't want a JIT failure when trying to execute the callback
|
||||
// because that would throw an exception through ESENT, corrupting it.
|
||||
// It is fine for the wrapped callback to fail because CallbackImpl
|
||||
// will catch the exception and deal with it.
|
||||
RuntimeHelpers.PrepareMethod(typeof(StatusCallbackWrapper).GetMethod(
|
||||
"CallbackImpl",
|
||||
BindingFlags.NonPublic | BindingFlags.Instance).MethodHandle);
|
||||
}
|
||||
#endif // !MANAGEDESENT_ON_WSA
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the JetCallbackWrapper class.
|
||||
/// </summary>
|
||||
/// <param name="callback">
|
||||
/// The managed callback to use.
|
||||
/// </param>
|
||||
public JetCallbackWrapper(JET_CALLBACK callback)
|
||||
{
|
||||
this.wrappedCallback = new WeakReference(callback);
|
||||
this.nativeCallback = this.CallbackImpl;
|
||||
Debug.Assert(this.wrappedCallback.IsAlive, "Callback isn't alive");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the wrapped callback has been garbage
|
||||
/// collected.
|
||||
/// </summary>
|
||||
public bool IsAlive
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.wrappedCallback.IsAlive;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a NATIVE_CALLBACK callback that wraps the managed callback.
|
||||
/// </summary>
|
||||
public NATIVE_CALLBACK NativeCallback
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.nativeCallback;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the callback is wrapping the specified JET_CALLBACK.
|
||||
/// </summary>
|
||||
/// <param name="callback">The callback.</param>
|
||||
/// <returns>True if this wrapper is wrapping the callback.</returns>
|
||||
public bool IsWrapping(JET_CALLBACK callback)
|
||||
{
|
||||
return callback.Equals(this.wrappedCallback.Target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback function for native code. We don't want to throw an exception through
|
||||
/// unmanaged ESENT because that will corrupt ESENT's internal state. Instead we
|
||||
/// catch all exceptions and return an error instead. We use a CER to make catching
|
||||
/// the exceptions as reliable as possible.
|
||||
/// </summary>
|
||||
/// <param name="nativeSesid">The session for which the callback is being made.</param>
|
||||
/// <param name="nativeDbid">The database for which the callback is being made.</param>
|
||||
/// <param name="nativeTableid">The cursor for which the callback is being made.</param>
|
||||
/// <param name="nativeCbtyp">The operation for which the callback is being made.</param>
|
||||
/// <param name="arg1">First callback-specific argument.</param>
|
||||
/// <param name="arg2">Second callback-specific argument.</param>
|
||||
/// <param name="nativeContext">Callback context.</param>
|
||||
/// <param name="unused">This parameter is not used.</param>
|
||||
/// <returns>An ESENT error code.</returns>
|
||||
private JET_err CallbackImpl(
|
||||
IntPtr nativeSesid,
|
||||
uint nativeDbid,
|
||||
IntPtr nativeTableid,
|
||||
uint nativeCbtyp,
|
||||
IntPtr arg1,
|
||||
IntPtr arg2,
|
||||
IntPtr nativeContext,
|
||||
IntPtr unused)
|
||||
{
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
var sesid = new JET_SESID { Value = nativeSesid };
|
||||
var dbid = new JET_DBID { Value = nativeDbid };
|
||||
var tableid = new JET_TABLEID { Value = nativeTableid };
|
||||
JET_cbtyp cbtyp = (JET_cbtyp)nativeCbtyp;
|
||||
|
||||
Debug.Assert(this.wrappedCallback.IsAlive, "Wrapped callback has been garbage collected");
|
||||
|
||||
// This will throw an exception if the wrapped callback has been collected. The exception
|
||||
// will be handled below.
|
||||
JET_CALLBACK callback = (JET_CALLBACK)this.wrappedCallback.Target;
|
||||
return callback(sesid, dbid, tableid, cbtyp, null, null, nativeContext, IntPtr.Zero);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Thread aborts aren't handled here. ESENT callbacks can execute on client threads or
|
||||
// internal ESENT threads so it isn't clear what should be done on an abort.
|
||||
Trace.WriteLineIf(
|
||||
TraceSwitch.TraceWarning,
|
||||
string.Format(CultureInfo.InvariantCulture, "Caught Exception {0}", ex));
|
||||
return JET_err.CallbackFailed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
67
WelsonJS.Toolkit/EsentInterop/JetCapabilities.cs
Normal file
67
WelsonJS.Toolkit/EsentInterop/JetCapabilities.cs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="JetCapabilities.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Implementation
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the functionality exposed by an object which implements IJetApi.
|
||||
/// </summary>
|
||||
internal sealed class JetCapabilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether Windows Server 2003 features
|
||||
/// (in the Interop.Server2003 namespace) are supported.
|
||||
/// </summary>
|
||||
public bool SupportsServer2003Features { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether Vista features (in the
|
||||
/// Interop.Vista namespace) are supported.
|
||||
/// </summary>
|
||||
public bool SupportsVistaFeatures { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether Win7 features (in the
|
||||
/// Interop.Windows7 namespace) are supported.
|
||||
/// </summary>
|
||||
public bool SupportsWindows7Features { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether Win8 features (in the
|
||||
/// Interop.Windows8 namespace) are supported.
|
||||
/// </summary>
|
||||
public bool SupportsWindows8Features { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether Win8.1 features (in the
|
||||
/// Interop.Windows81 namespace) are supported.
|
||||
/// </summary>
|
||||
public bool SupportsWindows81Features { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether Win10 features (in the
|
||||
/// Interop.Windows10 namespace) are supported.
|
||||
/// </summary>
|
||||
public bool SupportsWindows10Features { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether unicode file paths are supported.
|
||||
/// </summary>
|
||||
public bool SupportsUnicodePaths { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether large (> 255 byte) keys are supported.
|
||||
/// The key size for an index can be specified in the <see cref="JET_INDEXCREATE"/>
|
||||
/// object.
|
||||
/// </summary>
|
||||
public bool SupportsLargeKeys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum number of components in a sort or index key.
|
||||
/// </summary>
|
||||
public int ColumnsKeyMost { get; set; }
|
||||
}
|
||||
}
|
||||
191
WelsonJS.Toolkit/EsentInterop/Jet_indexcreate3.cs
Normal file
191
WelsonJS.Toolkit/EsentInterop/Jet_indexcreate3.cs
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="jet_indexcreate3.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Isam.Esent.Interop.Vista;
|
||||
|
||||
/// <summary>
|
||||
/// The native version of the JET_INDEXCREATE3 structure.
|
||||
/// </summary>
|
||||
[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 unsafe struct NATIVE_INDEXCREATE3
|
||||
{
|
||||
/// <summary>
|
||||
/// Size of the structure.
|
||||
/// </summary>
|
||||
public uint cbStruct;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the index.
|
||||
/// </summary>
|
||||
public IntPtr szIndexName;
|
||||
|
||||
/// <summary>
|
||||
/// Index key description.
|
||||
/// </summary>
|
||||
public IntPtr szKey;
|
||||
|
||||
/// <summary>
|
||||
/// Size of index key description.
|
||||
/// </summary>
|
||||
public uint cbKey;
|
||||
|
||||
/// <summary>
|
||||
/// Index options.
|
||||
/// </summary>
|
||||
public uint grbit;
|
||||
|
||||
/// <summary>
|
||||
/// Index density.
|
||||
/// </summary>
|
||||
public uint ulDensity;
|
||||
|
||||
/// <summary>
|
||||
/// Pointer to unicode sort options.
|
||||
/// </summary>
|
||||
public NATIVE_UNICODEINDEX2* pidxUnicode;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum size of column data to index. This can also be
|
||||
/// a pointer to a JET_TUPLELIMITS structure.
|
||||
/// </summary>
|
||||
public IntPtr cbVarSegMac;
|
||||
|
||||
/// <summary>
|
||||
/// Pointer to array of conditional columns.
|
||||
/// </summary>
|
||||
public IntPtr rgconditionalcolumn;
|
||||
|
||||
/// <summary>
|
||||
/// Count of conditional columns.
|
||||
/// </summary>
|
||||
public uint cConditionalColumn;
|
||||
|
||||
/// <summary>
|
||||
/// Returned error from index creation.
|
||||
/// </summary>
|
||||
public int err;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum size of the key.
|
||||
/// </summary>
|
||||
public uint cbKeyMost;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="NATIVE_SPACEHINTS"/> pointer.
|
||||
/// </summary>
|
||||
public IntPtr pSpaceHints;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains the information needed to create an index over data in an ESE database.
|
||||
/// </summary>
|
||||
public sealed partial class JET_INDEXCREATE : IContentEquatable<JET_INDEXCREATE>, IDeepCloneable<JET_INDEXCREATE>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the native (interop) version of this object, except for
|
||||
/// <see cref="szIndexName"/> and <see cref="szKey"/>.
|
||||
/// </summary>
|
||||
/// <remarks>The cbKey holds the length of the key in bytes, and does not need to be adjusted.</remarks>
|
||||
/// <returns>The native (interop) version of this object.</returns>
|
||||
internal NATIVE_INDEXCREATE3 GetNativeIndexcreate3()
|
||||
{
|
||||
this.CheckMembersAreValid();
|
||||
var native = new NATIVE_INDEXCREATE3();
|
||||
|
||||
native.cbStruct = checked((uint)Marshal.SizeOf(typeof(NATIVE_INDEXCREATE3)));
|
||||
|
||||
// szIndexName and szKey are converted at pinvoke time.
|
||||
//
|
||||
// native.szIndexName = this.szIndexName;
|
||||
// native.szKey = this.szKey;
|
||||
native.cbKey = checked((uint)this.cbKey * sizeof(char));
|
||||
native.grbit = unchecked((uint)this.grbit);
|
||||
native.ulDensity = checked((uint)this.ulDensity);
|
||||
|
||||
native.cbVarSegMac = new IntPtr(this.cbVarSegMac);
|
||||
|
||||
native.cConditionalColumn = checked((uint)this.cConditionalColumn);
|
||||
|
||||
if (0 != this.cbKeyMost)
|
||||
{
|
||||
native.cbKeyMost = checked((uint)this.cbKeyMost);
|
||||
native.grbit |= unchecked((uint)VistaGrbits.IndexKeyMost);
|
||||
}
|
||||
|
||||
return native;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets only the output fields of the object from a <see cref="NATIVE_INDEXCREATE3"/> struct,
|
||||
/// specifically <see cref="err"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// The native indexcreate to set the values from.
|
||||
/// </param>
|
||||
internal void SetFromNativeIndexCreate(ref NATIVE_INDEXCREATE3 value)
|
||||
{
|
||||
this.err = (JET_err)value.err;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets all of the fields (not just output fields) of the object from a <see cref="NATIVE_INDEXCREATE3"/> struct,
|
||||
/// specifically <see cref="err"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">
|
||||
/// The native indexcreate to set the values from.
|
||||
/// </param>
|
||||
internal void SetAllFromNativeIndexCreate(ref NATIVE_INDEXCREATE3 value)
|
||||
{
|
||||
this.szIndexName = Marshal.PtrToStringUni(value.szIndexName);
|
||||
this.cbKey = unchecked((int)value.cbKey / sizeof(char));
|
||||
this.szKey = Marshal.PtrToStringUni(value.szKey, this.cbKey);
|
||||
if (this.cbKey != this.szKey.Length)
|
||||
{
|
||||
throw new ArgumentException(string.Format("cbKey {0} != szKey.Length {1}", this.cbKey, this.szKey.Length));
|
||||
}
|
||||
|
||||
this.grbit = unchecked((CreateIndexGrbit)value.grbit);
|
||||
this.ulDensity = unchecked((int)value.ulDensity);
|
||||
|
||||
unsafe
|
||||
{
|
||||
this.pidxUnicode = new JET_UNICODEINDEX(ref *value.pidxUnicode);
|
||||
}
|
||||
|
||||
this.cbVarSegMac = (int)value.cbVarSegMac;
|
||||
this.cConditionalColumn = unchecked((int)value.cConditionalColumn);
|
||||
this.rgconditionalcolumn = new JET_CONDITIONALCOLUMN[this.cConditionalColumn];
|
||||
|
||||
int sizeofConditionalColumn = Marshal.SizeOf(typeof(NATIVE_CONDITIONALCOLUMN));
|
||||
for (int i = 0; i < this.cConditionalColumn; ++i)
|
||||
{
|
||||
IntPtr addressOfElement = value.rgconditionalcolumn + i * sizeofConditionalColumn;
|
||||
NATIVE_CONDITIONALCOLUMN nativeConditionalColumn =
|
||||
(NATIVE_CONDITIONALCOLUMN)Marshal.PtrToStructure(addressOfElement, typeof(NATIVE_CONDITIONALCOLUMN));
|
||||
this.rgconditionalcolumn[i] = new JET_CONDITIONALCOLUMN(ref nativeConditionalColumn);
|
||||
}
|
||||
|
||||
this.err = (JET_err)value.err;
|
||||
this.cbKeyMost = unchecked((int)value.cbKeyMost);
|
||||
|
||||
var nativeSpaceHints = (NATIVE_SPACEHINTS)Marshal.PtrToStructure(value.pSpaceHints, typeof(NATIVE_SPACEHINTS));
|
||||
this.pSpaceHints = new JET_SPACEHINTS();
|
||||
this.pSpaceHints.SetFromNativeSpaceHints(nativeSpaceHints);
|
||||
}
|
||||
}
|
||||
}
|
||||
97
WelsonJS.Toolkit/EsentInterop/Jet_opentemporarytable2.cs
Normal file
97
WelsonJS.Toolkit/EsentInterop/Jet_opentemporarytable2.cs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="jet_opentemporarytable2.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Vista
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
/// <summary>
|
||||
/// The native version of the JET_OPENTEMPORARYTABLE2 structure.
|
||||
/// </summary>
|
||||
[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 unsafe struct NATIVE_OPENTEMPORARYTABLE2
|
||||
{
|
||||
/// <summary>
|
||||
/// Size of the structure.
|
||||
/// </summary>
|
||||
public uint cbStruct;
|
||||
|
||||
/// <summary>
|
||||
/// Columns to create.
|
||||
/// </summary>
|
||||
public NATIVE_COLUMNDEF* prgcolumndef;
|
||||
|
||||
/// <summary>
|
||||
/// Number of entries in prgcolumndef.
|
||||
/// </summary>
|
||||
public uint ccolumn;
|
||||
|
||||
/// <summary>
|
||||
/// Optional pointer to unicode index information.
|
||||
/// </summary>
|
||||
public NATIVE_UNICODEINDEX2* pidxunicode;
|
||||
|
||||
/// <summary>
|
||||
/// Table options.
|
||||
/// </summary>
|
||||
public uint grbit;
|
||||
|
||||
/// <summary>
|
||||
/// Pointer to array of returned columnids. This
|
||||
/// should have at least ccolumn entries.
|
||||
/// </summary>
|
||||
public uint* rgcolumnid;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum key size.
|
||||
/// </summary>
|
||||
public uint cbKeyMost;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum amount of data used to construct a key.
|
||||
/// </summary>
|
||||
public uint cbVarSegMac;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the tableid of the new table.
|
||||
/// </summary>
|
||||
public IntPtr tableid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A collection of parameters for the JetOpenTemporaryTable method.
|
||||
/// </summary>
|
||||
public partial class JET_OPENTEMPORARYTABLE
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the unmanaged opentemporarytable that represents this managed class.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A native (interop) version of the JET_OPENTEMPORARYTABLE.
|
||||
/// </returns>
|
||||
internal NATIVE_OPENTEMPORARYTABLE2 GetNativeOpenTemporaryTable2()
|
||||
{
|
||||
this.CheckDataSize();
|
||||
var openTemporaryTable = new NATIVE_OPENTEMPORARYTABLE2();
|
||||
openTemporaryTable.cbStruct = checked((uint)Marshal.SizeOf(typeof(NATIVE_OPENTEMPORARYTABLE2)));
|
||||
openTemporaryTable.ccolumn = checked((uint)this.ccolumn);
|
||||
openTemporaryTable.grbit = (uint)this.grbit;
|
||||
openTemporaryTable.cbKeyMost = checked((uint)this.cbKeyMost);
|
||||
openTemporaryTable.cbVarSegMac = checked((uint)this.cbVarSegMac);
|
||||
return openTemporaryTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
159
WelsonJS.Toolkit/EsentInterop/Jet_tablecreate4.cs
Normal file
159
WelsonJS.Toolkit/EsentInterop/Jet_tablecreate4.cs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="jet_tablecreate4.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Isam.Esent.Interop.Implementation;
|
||||
|
||||
/// <summary>
|
||||
/// The native version of the <see cref="JET_TABLECREATE"/> structure. This includes callbacks,
|
||||
/// space hints, and uses NATIVE_INDEXCREATE4.
|
||||
/// </summary>
|
||||
[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 unsafe struct NATIVE_TABLECREATE4
|
||||
{
|
||||
/// <summary>
|
||||
/// Size of the structure.
|
||||
/// </summary>
|
||||
public uint cbStruct;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the table to create.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string szTableName;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the table from which to inherit base DDL.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string szTemplateTableName;
|
||||
|
||||
/// <summary>
|
||||
/// Initial pages to allocate for table.
|
||||
/// </summary>
|
||||
public uint ulPages;
|
||||
|
||||
/// <summary>
|
||||
/// Table density.
|
||||
/// </summary>
|
||||
public uint ulDensity;
|
||||
|
||||
/// <summary>
|
||||
/// Array of column creation info.
|
||||
/// </summary>
|
||||
public NATIVE_COLUMNCREATE* rgcolumncreate;
|
||||
|
||||
/// <summary>
|
||||
/// Number of columns to create.
|
||||
/// </summary>
|
||||
public uint cColumns;
|
||||
|
||||
/// <summary>
|
||||
/// Array of indices to create, pointer to <see cref="NATIVE_INDEXCREATE3"/>.
|
||||
/// </summary>
|
||||
public IntPtr rgindexcreate;
|
||||
|
||||
/// <summary>
|
||||
/// Number of indices to create.
|
||||
/// </summary>
|
||||
public uint cIndexes;
|
||||
|
||||
/// <summary>
|
||||
/// Callback function to use for the table.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string szCallback;
|
||||
|
||||
/// <summary>
|
||||
/// Type of the callback function.
|
||||
/// </summary>
|
||||
public JET_cbtyp cbtyp;
|
||||
|
||||
/// <summary>
|
||||
/// Table options.
|
||||
/// </summary>
|
||||
public uint grbit;
|
||||
|
||||
/// <summary>
|
||||
/// Space allocation, maintenance, and usage hints for default sequential index.
|
||||
/// </summary>
|
||||
public NATIVE_SPACEHINTS* pSeqSpacehints;
|
||||
|
||||
/// <summary>
|
||||
/// Space allocation, maintenance, and usage hints for Separated LV tree.
|
||||
/// </summary>
|
||||
public NATIVE_SPACEHINTS* pLVSpacehints;
|
||||
|
||||
/// <summary>
|
||||
/// Heuristic size to separate a intrinsic LV from the primary record.
|
||||
/// </summary>
|
||||
public uint cbSeparateLV;
|
||||
|
||||
/// <summary>
|
||||
/// Returned tableid.
|
||||
/// </summary>
|
||||
public IntPtr tableid;
|
||||
|
||||
/// <summary>
|
||||
/// Count of objects created (columns+table+indexes+callbacks).
|
||||
/// </summary>
|
||||
public uint cCreated;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains the information needed to create a table in an ESE database.
|
||||
/// </summary>
|
||||
public partial class JET_TABLECREATE : IContentEquatable<JET_TABLECREATE>, IDeepCloneable<JET_TABLECREATE>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the native (interop) version of this object. The following members are
|
||||
/// NOT converted: <see cref="rgcolumncreate"/>, <see cref="rgindexcreate"/>,
|
||||
/// <see cref="pSeqSpacehints"/>, and <see cref="pLVSpacehints"/>.
|
||||
/// </summary>
|
||||
/// <returns>The native (interop) version of this object.</returns>
|
||||
internal NATIVE_TABLECREATE4 GetNativeTableCreate4()
|
||||
{
|
||||
this.CheckMembersAreValid();
|
||||
|
||||
var native = new NATIVE_TABLECREATE4();
|
||||
native.cbStruct = checked((uint)Marshal.SizeOf(typeof(NATIVE_TABLECREATE4)));
|
||||
native.szTableName = this.szTableName;
|
||||
native.szTemplateTableName = this.szTemplateTableName;
|
||||
native.ulPages = checked((uint)this.ulPages);
|
||||
native.ulDensity = checked((uint)this.ulDensity);
|
||||
|
||||
// native.rgcolumncreate is done at pinvoke time.
|
||||
native.cColumns = checked((uint)this.cColumns);
|
||||
|
||||
// native.rgindexcreate is done at pinvoke time.
|
||||
native.cIndexes = checked((uint)this.cIndexes);
|
||||
native.szCallback = this.szCallback;
|
||||
native.cbtyp = this.cbtyp;
|
||||
native.grbit = checked((uint)this.grbit);
|
||||
|
||||
// native.pSeqSpacehints is done at pinvoke time.
|
||||
// native.pLVSpacehints is done at pinvoke time.
|
||||
native.cbSeparateLV = checked((uint)this.cbSeparateLV);
|
||||
native.tableid = this.tableid.Value;
|
||||
native.cCreated = checked((uint)this.cCreated);
|
||||
|
||||
return native;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
WelsonJS.Toolkit/EsentInterop/LegacyFileNames.cs
Normal file
26
WelsonJS.Toolkit/EsentInterop/LegacyFileNames.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="LegacyFileNames.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Vista
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for LegacyFileNames.
|
||||
/// </summary>
|
||||
public enum LegacyFileNames
|
||||
{
|
||||
/// <summary>
|
||||
/// When this option is present then the database engine will use the following naming conventions for its files:
|
||||
/// o Transaction Log files will use .LOG for their file extension.
|
||||
/// o Checkpoint files will use .CHK for their file extension.
|
||||
/// </summary>
|
||||
ESE98FileNames = 0x00000001,
|
||||
|
||||
/// <summary>
|
||||
/// Preserve the 8.3 naming syntax for as long as possible. (this should not be changed, w/o ensuring there are no log files).
|
||||
/// </summary>
|
||||
EightDotThreeSoftCompat = 0x00000002,
|
||||
}
|
||||
}
|
||||
273
WelsonJS.Toolkit/EsentInterop/LibraryHelpers.cs
Normal file
273
WelsonJS.Toolkit/EsentInterop/LibraryHelpers.cs
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="LibraryHelpers.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using Microsoft.Isam.Esent.Interop.Implementation;
|
||||
|
||||
/// <summary>
|
||||
/// Contains several helper functions that are useful in the test binary.
|
||||
/// In particular, it contains functionality that is not available in
|
||||
/// reduced-functionality environments (such as CoreClr).
|
||||
/// </summary>
|
||||
internal static class LibraryHelpers
|
||||
{
|
||||
/// <summary>Provides a platform-specific character used to separate directory levels in a path string that reflects a hierarchical file system organization.</summary>
|
||||
/// <filterpriority>1</filterpriority>
|
||||
public static readonly char DirectorySeparatorChar = '\\';
|
||||
|
||||
/// <summary>Provides a platform-specific alternate character used to separate directory levels in a path string that reflects a hierarchical file system organization.</summary>
|
||||
/// <filterpriority>1</filterpriority>
|
||||
public static readonly char AltDirectorySeparatorChar = '/';
|
||||
|
||||
/// <summary>
|
||||
/// Gets an ASCII encoder.
|
||||
/// </summary>
|
||||
public static Encoding EncodingASCII
|
||||
{
|
||||
get
|
||||
{
|
||||
#if MANAGEDESENT_ON_CORECLR
|
||||
return SlowAsciiEncoding.Encoding;
|
||||
#else
|
||||
return Encoding.ASCII;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a new ASCII encoder. It's preferred to use EncodingASCII, but some applications (e.g. tests)
|
||||
/// may want a different Encoding object.
|
||||
/// </summary>
|
||||
public static Encoding NewEncodingASCII
|
||||
{
|
||||
get
|
||||
{
|
||||
#if MANAGEDESENT_ON_CORECLR
|
||||
return new SlowAsciiEncoding();
|
||||
#else
|
||||
return new ASCIIEncoding();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// This should be dead code when running on Core CLR; This is only called by
|
||||
// GetIndexInfoFromIndexlist() when called on a pre-Win8 system, and Core CLR
|
||||
// is only on Win8 anyway.
|
||||
#if !MANAGEDESENT_ON_CORECLR
|
||||
/// <summary>
|
||||
/// Creates a CultureInfo object when given the LCID.
|
||||
/// </summary>
|
||||
/// <param name="lcid">
|
||||
/// The lcid passed in.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A CultureInfo object.
|
||||
/// </returns>
|
||||
public static CultureInfo CreateCultureInfoByLcid(int lcid)
|
||||
{
|
||||
return new CultureInfo(lcid);
|
||||
}
|
||||
#endif // !MANAGEDESENT_ON_CORECLR
|
||||
|
||||
/// <summary>
|
||||
/// Allocates memory on the native heap.
|
||||
/// </summary>
|
||||
/// <returns>A pointer to native memory.</returns>
|
||||
/// <param name="size">The size of the memory desired.</param>
|
||||
public static IntPtr MarshalAllocHGlobal(int size)
|
||||
{
|
||||
#if MANAGEDESENT_ON_CORECLR && !MANAGEDESENT_ON_WSA
|
||||
return Win32.NativeMethods.LocalAlloc(0, new UIntPtr((uint)size));
|
||||
#else
|
||||
return Marshal.AllocHGlobal(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Frees memory that was allocated on the native heap.
|
||||
/// </summary>
|
||||
/// <param name="buffer">A pointer to native memory.</param>
|
||||
public static void MarshalFreeHGlobal(IntPtr buffer)
|
||||
{
|
||||
#if MANAGEDESENT_ON_CORECLR && !MANAGEDESENT_ON_WSA
|
||||
Win32.NativeMethods.LocalFree(buffer);
|
||||
#else
|
||||
Marshal.FreeHGlobal(buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>Copies the contents of a managed <see cref="T:System.String" /> into unmanaged memory.</summary>
|
||||
/// <returns>The address, in unmanaged memory, to where the <paramref name="managedString" /> was copied, or 0 if <paramref name="managedString" /> is null.</returns>
|
||||
/// <param name="managedString">A managed string to be copied.</param>
|
||||
/// <exception cref="T:System.OutOfMemoryException">The method could not allocate enough native heap memory.</exception>
|
||||
/// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="managedString" /> parameter exceeds the maximum length allowed by the operating system.</exception>
|
||||
public static IntPtr MarshalStringToHGlobalUni(string managedString)
|
||||
{
|
||||
#if MANAGEDESENT_ON_CORECLR && !MANAGEDESENT_ON_WSA
|
||||
return MyStringToHGlobalUni(managedString);
|
||||
#else
|
||||
return Marshal.StringToHGlobalUni(managedString);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the managed ID of the current thread.
|
||||
/// </summary>
|
||||
/// <returns>The ID of the current thread.</returns>
|
||||
public static int GetCurrentManagedThreadId()
|
||||
{
|
||||
#if MANAGEDESENT_ON_CORECLR
|
||||
return Environment.CurrentManagedThreadId;
|
||||
#else
|
||||
return Thread.CurrentThread.ManagedThreadId;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancels an <see cref="M:System.Threading.Thread.Abort(System.Object)"/> requested for the current thread.
|
||||
/// </summary>
|
||||
/// <exception cref="T:System.Threading.ThreadStateException">Abort was not invoked on the current thread. </exception><exception cref="T:System.Security.SecurityException">The caller does not have the required security permission for the current thread. </exception><filterpriority>2</filterpriority><PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="ControlThread"/></PermissionSet>
|
||||
public static void ThreadResetAbort()
|
||||
{
|
||||
#if MANAGEDESENT_ON_CORECLR
|
||||
// Do nothing.
|
||||
#else
|
||||
Thread.ResetAbort();
|
||||
#endif
|
||||
}
|
||||
|
||||
// FUTURE-2013/12/16-martinc. It appears that all of this hacking for running on Core CLR may no longer be necessary.
|
||||
// We initially ported to an early version of Core CLR that had a lot of functionality missing. By the time
|
||||
// Windows Store Apps came out in Windows 8, many of these functions were added back.
|
||||
#if MANAGEDESENT_ON_CORECLR && !MANAGEDESENT_ON_WSA
|
||||
// System.Runtime.InteropServices.Marshal
|
||||
|
||||
/// <summary>Copies the contents of a managed <see cref="T:System.String" /> into unmanaged memory.</summary>
|
||||
/// <returns>The address, in unmanaged memory, to where the <paramref name="managedString" /> was copied, or 0 if <paramref name="managedString" /> is null.</returns>
|
||||
/// <param name="managedString">A managed string to be copied.</param>
|
||||
/// <exception cref="T:System.OutOfMemoryException">The method could not allocate enough native heap memory.</exception>
|
||||
/// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="managedString" /> parameter exceeds the maximum length allowed by the operating system.</exception>
|
||||
[SecurityCritical]
|
||||
private static unsafe IntPtr MyStringToHGlobalUni(string managedString)
|
||||
{
|
||||
if (managedString == null)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
int charCountWithNull = managedString.Length + 1;
|
||||
int byteCount = charCountWithNull * sizeof(char);
|
||||
|
||||
if (byteCount < managedString.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("managedString");
|
||||
}
|
||||
|
||||
UIntPtr sizetdwBytes = new UIntPtr((uint)byteCount);
|
||||
IntPtr rawBuffer = Win32.NativeMethods.LocalAlloc(0, sizetdwBytes);
|
||||
if (rawBuffer == IntPtr.Zero)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
fixed (char* sourcePointer = managedString)
|
||||
{
|
||||
byte* destPointer = (byte*)rawBuffer;
|
||||
var unicodeEncoding = new System.Text.UnicodeEncoding();
|
||||
int bytesWritten = unicodeEncoding.GetBytes(sourcePointer, charCountWithNull, destPointer, byteCount);
|
||||
}
|
||||
|
||||
return rawBuffer;
|
||||
}
|
||||
#endif // MANAGEDESENT_ON_CORECLR && !MANAGEDESENT_ON_WSA
|
||||
|
||||
/// <summary>Returns a <see cref="T:System.DateTime" /> equivalent to the specified OLE Automation Date.</summary>
|
||||
/// <returns>A <see cref="T:System.DateTime" /> that represents the same date and time as <paramref name="d" />.</returns>
|
||||
/// <param name="d">An OLE Automation Date value. </param>
|
||||
/// <exception cref="T:System.ArgumentException">The date is not a valid OLE Automation Date value. </exception>
|
||||
/// <filterpriority>1</filterpriority>
|
||||
public static DateTime FromOADate(double d)
|
||||
{
|
||||
#if MANAGEDESENT_ON_CORECLR
|
||||
return new DateTime(DoubleDateToTicks(d), DateTimeKind.Unspecified);
|
||||
#else
|
||||
return DateTime.FromOADate(d);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MANAGEDESENT_ON_CORECLR
|
||||
/// <summary>
|
||||
/// Copied from the reflected implementation.
|
||||
/// </summary>
|
||||
/// <param name="value">The date, as a 64bit integer.</param>
|
||||
/// <returns>The date, as a double representation.</returns>
|
||||
internal static double TicksToOADate(long value)
|
||||
{
|
||||
if (value == 0L)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (value < 864000000000L)
|
||||
{
|
||||
value += 599264352000000000L;
|
||||
}
|
||||
|
||||
if (value < 31241376000000000L)
|
||||
{
|
||||
throw new OverflowException();
|
||||
}
|
||||
|
||||
long num = (value - 599264352000000000L) / 10000L;
|
||||
if (num < 0L)
|
||||
{
|
||||
long num2 = num % 86400000L;
|
||||
if (num2 != 0L)
|
||||
{
|
||||
num -= (86400000L + num2) * 2L;
|
||||
}
|
||||
}
|
||||
|
||||
return (double)num / 86400000.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copied from the reflected implementation.
|
||||
/// </summary>
|
||||
/// <param name="value">The date, as a double representation.</param>
|
||||
/// <returns>The date, as a 64bit integer.</returns>
|
||||
internal static long DoubleDateToTicks(double value)
|
||||
{
|
||||
if (value >= 2958466.0 || value <= -657435.0)
|
||||
{
|
||||
throw new ArgumentException("value does not represent a valid date", "value");
|
||||
}
|
||||
|
||||
long num = (long)((value * 86400000.0) + ((value >= 0.0) ? 0.5 : -0.5));
|
||||
if (num < 0L)
|
||||
{
|
||||
num -= (num % 86400000L) * 2L;
|
||||
}
|
||||
|
||||
num += 59926435200000L;
|
||||
if (num < 0L || num >= 315537897600000L)
|
||||
{
|
||||
throw new ArgumentException("value does not represent a valid date", "value");
|
||||
}
|
||||
|
||||
return num * 10000L;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
321
WelsonJS.Toolkit/EsentInterop/MakeKeyHelpers.cs
Normal file
321
WelsonJS.Toolkit/EsentInterop/MakeKeyHelpers.cs
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="MakeKeyHelpers.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Helper methods for the ESENT API. These do data conversion for
|
||||
/// JetMakeKey.
|
||||
/// </summary>
|
||||
public static partial class Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, byte[] data, MakeKeyGrbit grbit)
|
||||
{
|
||||
if (null == data)
|
||||
{
|
||||
Api.JetMakeKey(sesid, tableid, null, 0, grbit);
|
||||
}
|
||||
else if (0 == data.Length)
|
||||
{
|
||||
Api.JetMakeKey(sesid, tableid, data, data.Length, grbit | MakeKeyGrbit.KeyDataZeroLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
Api.JetMakeKey(sesid, tableid, data, data.Length, grbit);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="encoding">The encoding used to convert the string.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, string data, Encoding encoding, MakeKeyGrbit grbit)
|
||||
{
|
||||
CheckEncodingIsValid(encoding);
|
||||
|
||||
if (null == data)
|
||||
{
|
||||
Api.JetMakeKey(sesid, tableid, null, 0, grbit);
|
||||
}
|
||||
else if (0 == data.Length)
|
||||
{
|
||||
Api.JetMakeKey(sesid, tableid, null, 0, grbit | MakeKeyGrbit.KeyDataZeroLength);
|
||||
}
|
||||
else if (Encoding.Unicode == encoding)
|
||||
{
|
||||
// Optimization for Unicode strings
|
||||
unsafe
|
||||
{
|
||||
fixed (char* buffer = data)
|
||||
{
|
||||
Api.JetMakeKey(sesid, tableid, new IntPtr(buffer), checked(data.Length * sizeof(char)), grbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if MANAGEDESENT_ON_WSA
|
||||
// Encoding.GetBytes(char*, int, byte*, int) overload is missing in new Windows UI.
|
||||
// So we can't use the ColumnCache. We'll just use a different GetBytes() overload.
|
||||
byte[] buffer = encoding.GetBytes(data);
|
||||
Api.JetMakeKey(sesid, tableid, buffer, buffer.Length, grbit);
|
||||
#else
|
||||
// Convert the string using a cached column buffer. The column buffer is far larger
|
||||
// than the maximum key size, so any data truncation here won't matter.
|
||||
byte[] buffer = null;
|
||||
try
|
||||
{
|
||||
buffer = Caches.ColumnCache.Allocate();
|
||||
int dataSize;
|
||||
unsafe
|
||||
{
|
||||
fixed (char* chars = data)
|
||||
fixed (byte* bytes = buffer)
|
||||
{
|
||||
dataSize = encoding.GetBytes(chars, data.Length, bytes, buffer.Length);
|
||||
}
|
||||
}
|
||||
|
||||
JetMakeKey(sesid, tableid, buffer, dataSize, grbit);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
Caches.ColumnCache.Free(ref buffer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, bool data, MakeKeyGrbit grbit)
|
||||
{
|
||||
byte b = data ? (byte)0xff : (byte)0x0;
|
||||
Api.MakeKey(sesid, tableid, b, grbit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, byte data, MakeKeyGrbit grbit)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(byte);
|
||||
var pointer = new IntPtr(&data);
|
||||
Api.JetMakeKey(sesid, tableid, pointer, DataSize, grbit);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, short data, MakeKeyGrbit grbit)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(short);
|
||||
var pointer = new IntPtr(&data);
|
||||
Api.JetMakeKey(sesid, tableid, pointer, DataSize, grbit);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, int data, MakeKeyGrbit grbit)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(int);
|
||||
var pointer = new IntPtr(&data);
|
||||
Api.JetMakeKey(sesid, tableid, pointer, DataSize, grbit);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, long data, MakeKeyGrbit grbit)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(long);
|
||||
var pointer = new IntPtr(&data);
|
||||
Api.JetMakeKey(sesid, tableid, pointer, DataSize, grbit);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, Guid data, MakeKeyGrbit grbit)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = 16 /* sizeof(Guid) */;
|
||||
var pointer = new IntPtr(&data);
|
||||
Api.JetMakeKey(sesid, tableid, pointer, DataSize, grbit);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, DateTime data, MakeKeyGrbit grbit)
|
||||
{
|
||||
Api.MakeKey(sesid, tableid, data.ToOADate(), grbit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, float data, MakeKeyGrbit grbit)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(float);
|
||||
var pointer = new IntPtr(&data);
|
||||
Api.JetMakeKey(sesid, tableid, pointer, DataSize, grbit);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, double data, MakeKeyGrbit grbit)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(double);
|
||||
var pointer = new IntPtr(&data);
|
||||
Api.JetMakeKey(sesid, tableid, pointer, DataSize, grbit);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
[CLSCompliant(false)]
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, ushort data, MakeKeyGrbit grbit)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(ushort);
|
||||
var pointer = new IntPtr(&data);
|
||||
Api.JetMakeKey(sesid, tableid, pointer, DataSize, grbit);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
[CLSCompliant(false)]
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, uint data, MakeKeyGrbit grbit)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(uint);
|
||||
var pointer = new IntPtr(&data);
|
||||
Api.JetMakeKey(sesid, tableid, pointer, DataSize, grbit);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a search key that may then be used by <see cref="JetSeek"/>
|
||||
/// and <see cref="JetSetIndexRange"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to create the key on.</param>
|
||||
/// <param name="data">Column data for the current key column of the current index.</param>
|
||||
/// <param name="grbit">Key options.</param>
|
||||
[CLSCompliant(false)]
|
||||
public static void MakeKey(JET_SESID sesid, JET_TABLEID tableid, ulong data, MakeKeyGrbit grbit)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(ulong);
|
||||
var pointer = new IntPtr(&data);
|
||||
Api.JetMakeKey(sesid, tableid, pointer, DataSize, grbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
151
WelsonJS.Toolkit/EsentInterop/MemoryCache.cs
Normal file
151
WelsonJS.Toolkit/EsentInterop/MemoryCache.cs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="MemoryCache.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// Cache allocated chunks of memory that are needed for very short periods
|
||||
/// of time. The memory is not zeroed on allocation.
|
||||
/// </summary>
|
||||
internal sealed class MemoryCache
|
||||
{
|
||||
/// <summary>
|
||||
/// A zero-length array that should be used whenever we want to return one.
|
||||
/// </summary>
|
||||
private static readonly byte[] ZeroLengthArray = new byte[0];
|
||||
|
||||
/// <summary>
|
||||
/// Default size for newly allocated buffers.
|
||||
/// </summary>
|
||||
private readonly int bufferSize;
|
||||
|
||||
/// <summary>
|
||||
/// Currently cached buffers.
|
||||
/// </summary>
|
||||
private readonly byte[][] cachedBuffers;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MemoryCache"/> class.
|
||||
/// </summary>
|
||||
/// <param name="bufferSize">
|
||||
/// The size of the buffers to cache.
|
||||
/// </param>
|
||||
/// <param name="maxCachedBuffers">
|
||||
/// The maximum number of buffers to cache.
|
||||
/// </param>
|
||||
public MemoryCache(int bufferSize, int maxCachedBuffers)
|
||||
{
|
||||
this.bufferSize = bufferSize;
|
||||
this.cachedBuffers = new byte[maxCachedBuffers][];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the buffers that this cache returns.
|
||||
/// </summary>
|
||||
public int BufferSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.bufferSize;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new array containing a copy of 'length' bytes of data.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to copy.</param>
|
||||
/// <param name="length">The length of data to copy.</param>
|
||||
/// <returns>An array containing the first length bytes of data.</returns>
|
||||
public static byte[] Duplicate(byte[] data, int length)
|
||||
{
|
||||
Debug.Assert(data.Length >= length, "length parameter is too long");
|
||||
if (0 == length)
|
||||
{
|
||||
return ZeroLengthArray;
|
||||
}
|
||||
|
||||
var output = new byte[length];
|
||||
Buffer.BlockCopy(data, 0, output, 0, length);
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocates a chunk of memory. If memory is cached it is returned. If no memory
|
||||
/// is cached then it is allocated. Check the size of the returned buffer to determine
|
||||
/// how much memory was allocated.
|
||||
/// </summary>
|
||||
/// <returns>A new memory buffer.</returns>
|
||||
public byte[] Allocate()
|
||||
{
|
||||
int offset = this.GetStartingOffset();
|
||||
for (int i = 0; i < this.cachedBuffers.Length; ++i)
|
||||
{
|
||||
int index = (i + offset) % this.cachedBuffers.Length;
|
||||
byte[] buffer = Interlocked.Exchange(ref this.cachedBuffers[index], null);
|
||||
if (null != buffer)
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return new byte[this.bufferSize];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Frees an unused buffer. This may be added to the cache.
|
||||
/// </summary>
|
||||
/// <param name="data">The memory to free.</param>
|
||||
public void Free(ref byte[] data)
|
||||
{
|
||||
if (null == data)
|
||||
{
|
||||
throw new ArgumentNullException("data");
|
||||
}
|
||||
|
||||
if (data.Length != this.bufferSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("data", data.Length, "buffer is not correct size for this MemoryCache");
|
||||
}
|
||||
|
||||
int offset = this.GetStartingOffset();
|
||||
|
||||
// The buffers are garbage collected so we don't need to make Free()
|
||||
// completely safe. In a multi-threaded situation we may see a null
|
||||
// slot and then overwrite a buffer which was just freed into the slot.
|
||||
// That will cause us to lose a buffer which could have been placed
|
||||
// in a different slot, but in return we can do the Free() without
|
||||
// expensive interlocked operations.
|
||||
for (int i = 0; i < this.cachedBuffers.Length; ++i)
|
||||
{
|
||||
int index = (i + offset) % this.cachedBuffers.Length;
|
||||
if (null == this.cachedBuffers[index])
|
||||
{
|
||||
this.cachedBuffers[index] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the offset in the cached buffers array to start allocating or freeing
|
||||
/// buffers to. This is done so that all threads don't start operating on
|
||||
/// slot zero, which would increase contention.
|
||||
/// </summary>
|
||||
/// <returns>The starting offset for Allocate/Free operations.</returns>
|
||||
private int GetStartingOffset()
|
||||
{
|
||||
// Using the current CPU number would be ideal, but there doesn't seem to
|
||||
// be a cheap way to get that information in managed code.
|
||||
return LibraryHelpers.GetCurrentManagedThreadId() % this.cachedBuffers.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
294
WelsonJS.Toolkit/EsentInterop/MetaDataHelpers.cs
Normal file
294
WelsonJS.Toolkit/EsentInterop/MetaDataHelpers.cs
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="MetaDataHelpers.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Microsoft.Isam.Esent.Interop.Implementation;
|
||||
|
||||
/// <summary>
|
||||
/// Helper methods for the ESENT API. These methods deal with database
|
||||
/// meta-data.
|
||||
/// </summary>
|
||||
public static partial class Api
|
||||
{
|
||||
#region Simpler API. Overloads that omit unused/obsolete parameters.
|
||||
/// <summary>
|
||||
/// Initialize a new ESENT session.
|
||||
/// </summary>
|
||||
/// <param name="instance">The initialized instance to create the session in.</param>
|
||||
/// <param name="sesid">Returns the created session.</param>
|
||||
public static void BeginSession(JET_INSTANCE instance, out JET_SESID sesid)
|
||||
{
|
||||
Api.JetBeginSession(instance, out sesid, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and attaches a database file.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="database">The path to the database file to create.</param>
|
||||
/// <param name="dbid">Returns the dbid of the new database.</param>
|
||||
/// <param name="grbit">Database creation options.</param>
|
||||
public static void CreateDatabase(JET_SESID sesid, string database, out JET_DBID dbid, CreateDatabaseGrbit grbit)
|
||||
{
|
||||
Api.JetCreateDatabase(sesid, database, null, out dbid, grbit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a database previously attached with <see cref="JetAttachDatabase"/>,
|
||||
/// for use with a database session. This function can be called multiple times
|
||||
/// for the same database.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session that is opening the database.</param>
|
||||
/// <param name="database">The database to open.</param>
|
||||
/// <param name="dbid">Returns the dbid of the attached database.</param>
|
||||
/// <param name="grbit">Open database options.</param>
|
||||
/// <returns>An ESENT warning code.</returns>
|
||||
public static JET_wrn OpenDatabase(
|
||||
JET_SESID sesid,
|
||||
string database,
|
||||
out JET_DBID dbid,
|
||||
OpenDatabaseGrbit grbit)
|
||||
{
|
||||
return Api.JetOpenDatabase(sesid, database, null, out dbid, grbit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a cursor on a previously created table.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The database session to use.</param>
|
||||
/// <param name="dbid">The database to open the table in.</param>
|
||||
/// <param name="tablename">The name of the table to open.</param>
|
||||
/// <param name="grbit">Table open options.</param>
|
||||
/// <param name="tableid">Returns the opened table.</param>
|
||||
/// <returns>An ESENT warning.</returns>
|
||||
public static JET_wrn OpenTable(
|
||||
JET_SESID sesid,
|
||||
JET_DBID dbid,
|
||||
string tablename,
|
||||
OpenTableGrbit grbit,
|
||||
out JET_TABLEID tableid)
|
||||
{
|
||||
return Api.JetOpenTable(sesid, dbid, tablename, null, 0, grbit, out tableid);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Try to open a table.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="dbid">The database to look for the table in.</param>
|
||||
/// <param name="tablename">The name of the table.</param>
|
||||
/// <param name="grbit">Table open options.</param>
|
||||
/// <param name="tableid">Returns the opened tableid.</param>
|
||||
/// <returns>True if the table was opened, false if the table doesn't exist.</returns>
|
||||
public static bool TryOpenTable(
|
||||
JET_SESID sesid,
|
||||
JET_DBID dbid,
|
||||
string tablename,
|
||||
OpenTableGrbit grbit,
|
||||
out JET_TABLEID tableid)
|
||||
{
|
||||
var err = (JET_err)Impl.JetOpenTable(sesid, dbid, tablename, null, 0, grbit, out tableid);
|
||||
if (JET_err.ObjectNotFound == err)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Api.Check((int)err);
|
||||
Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a dictionary which maps column names to their column IDs.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The sesid to use.</param>
|
||||
/// <param name="tableid">The table to retrieve the information for.</param>
|
||||
/// <returns>A dictionary mapping column names to column IDs.</returns>
|
||||
public static IDictionary<string, JET_COLUMNID> GetColumnDictionary(JET_SESID sesid, JET_TABLEID tableid)
|
||||
{
|
||||
JET_COLUMNLIST columnlist;
|
||||
JetGetTableColumnInfo(sesid, tableid, string.Empty, out columnlist);
|
||||
|
||||
// As of Sep 2015, JetGetColumnInfoW is only called for Win8+. Even though Unicode should have
|
||||
// worked in Win7, it wasn't reliable until Win8.
|
||||
Encoding encodingOfTextColumns = EsentVersion.SupportsWindows8Features ? Encoding.Unicode : LibraryHelpers.EncodingASCII;
|
||||
|
||||
try
|
||||
{
|
||||
// esent treats column names as case-insensitive, so we want the dictionary to be case insensitive as well
|
||||
var dict = new Dictionary<string, JET_COLUMNID>(
|
||||
columnlist.cRecord, StringComparer.OrdinalIgnoreCase);
|
||||
if (columnlist.cRecord > 0)
|
||||
{
|
||||
if (Api.TryMoveFirst(sesid, columnlist.tableid))
|
||||
{
|
||||
do
|
||||
{
|
||||
string name = RetrieveColumnAsString(
|
||||
sesid,
|
||||
columnlist.tableid,
|
||||
columnlist.columnidcolumnname,
|
||||
encodingOfTextColumns,
|
||||
RetrieveColumnGrbit.None);
|
||||
name = StringCache.TryToIntern(name);
|
||||
var columnidValue =
|
||||
(uint)RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcolumnid);
|
||||
|
||||
var columnid = new JET_COLUMNID { Value = columnidValue };
|
||||
dict.Add(name, columnid);
|
||||
}
|
||||
while (TryMoveNext(sesid, columnlist.tableid));
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Close the temporary table used to return the results
|
||||
JetCloseTable(sesid, columnlist.tableid);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the columnid of the specified column.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The table containing the column.</param>
|
||||
/// <param name="columnName">The name of the column.</param>
|
||||
/// <returns>The id of the column.</returns>
|
||||
public static JET_COLUMNID GetTableColumnid(JET_SESID sesid, JET_TABLEID tableid, string columnName)
|
||||
{
|
||||
JET_COLUMNDEF columndef;
|
||||
JetGetTableColumnInfo(sesid, tableid, columnName, out columndef);
|
||||
return columndef.columnid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates over all the columns in the table, returning information about each one.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The table to retrieve column information for.</param>
|
||||
/// <returns>An iterator over ColumnInfo for each column in the table.</returns>
|
||||
public static IEnumerable<ColumnInfo> GetTableColumns(JET_SESID sesid, JET_TABLEID tableid)
|
||||
{
|
||||
return new GenericEnumerable<ColumnInfo>(() => new TableidColumnInfoEnumerator(sesid, tableid));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates over all the columns in the table, returning information about each one.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="dbid">The database containing the table.</param>
|
||||
/// <param name="tablename">The name of the table.</param>
|
||||
/// <returns>An iterator over ColumnInfo for each column in the table.</returns>
|
||||
public static IEnumerable<ColumnInfo> GetTableColumns(JET_SESID sesid, JET_DBID dbid, string tablename)
|
||||
{
|
||||
if (null == tablename)
|
||||
{
|
||||
throw new ArgumentNullException("tablename");
|
||||
}
|
||||
|
||||
return new GenericEnumerable<ColumnInfo>(() => new TableColumnInfoEnumerator(sesid, dbid, tablename));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates over all the indexes in the table, returning information about each one.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The table to retrieve index information for.</param>
|
||||
/// <returns>An iterator over an IndexInfo for each index in the table.</returns>
|
||||
public static IEnumerable<IndexInfo> GetTableIndexes(JET_SESID sesid, JET_TABLEID tableid)
|
||||
{
|
||||
return new GenericEnumerable<IndexInfo>(() => new TableidIndexInfoEnumerator(sesid, tableid));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates over all the indexs in the table, returning information about each one.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="dbid">The database containing the table.</param>
|
||||
/// <param name="tablename">The name of the table.</param>
|
||||
/// <returns>An iterator over an IndexInfo for each index in the table.</returns>
|
||||
public static IEnumerable<IndexInfo> GetTableIndexes(JET_SESID sesid, JET_DBID dbid, string tablename)
|
||||
{
|
||||
if (null == tablename)
|
||||
{
|
||||
throw new ArgumentNullException("tablename");
|
||||
}
|
||||
|
||||
return new GenericEnumerable<IndexInfo>(() => new TableIndexInfoEnumerator(sesid, dbid, tablename));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the names of the tables in the database.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="dbid">The database containing the table.</param>
|
||||
/// <returns>An iterator over the names of the tables in the database.</returns>
|
||||
public static IEnumerable<string> GetTableNames(JET_SESID sesid, JET_DBID dbid)
|
||||
{
|
||||
return new GenericEnumerable<string>(() => new TableNameEnumerator(sesid, dbid));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves information about indexes on a table.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The table to retrieve index information about.</param>
|
||||
/// <param name="indexname">The name of the index.</param>
|
||||
/// <param name="result">Filled in with information about indexes on the table.</param>
|
||||
/// <param name="infoLevel">The type of information to retrieve.</param>
|
||||
/// <returns>true if there was no error, false if the index wasn't found. Throws for other Jet errors.</returns>
|
||||
public static bool TryJetGetTableIndexInfo(
|
||||
JET_SESID sesid,
|
||||
JET_TABLEID tableid,
|
||||
string indexname,
|
||||
out JET_INDEXID result,
|
||||
JET_IdxInfo infoLevel)
|
||||
{
|
||||
int err = Impl.JetGetTableIndexInfo(sesid, tableid, indexname, out result, infoLevel);
|
||||
|
||||
if ((JET_err)err == JET_err.IndexNotFound)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Api.Check(err);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the name of the current index of a given cursor.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This name is also used to later re-select that index as the current index using
|
||||
/// <see cref="JetSetCurrentIndex"/>. It can also be used to discover the properties of that index using
|
||||
/// JetGetTableIndexInfo.
|
||||
///
|
||||
/// The returned name of the index will be null if the current index is the clustered index and no primary
|
||||
/// index was explicitly defined.
|
||||
/// </remarks>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to get the index name for.</param>
|
||||
/// <returns>Returns the name of the index.</returns>
|
||||
public static string JetGetCurrentIndex(JET_SESID sesid, JET_TABLEID tableid)
|
||||
{
|
||||
string indexName;
|
||||
Api.JetGetCurrentIndex(sesid, tableid, out indexName, SystemParameters.NameMost);
|
||||
|
||||
return string.IsNullOrEmpty(indexName) ? null : indexName;
|
||||
}
|
||||
}
|
||||
}
|
||||
244
WelsonJS.Toolkit/EsentInterop/MoveHelpers.cs
Normal file
244
WelsonJS.Toolkit/EsentInterop/MoveHelpers.cs
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="MoveHelpers.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// Helper methods for the ESENT API. These aren't interop versions
|
||||
/// of the API, but encapsulate very common uses of the functions.
|
||||
/// </summary>
|
||||
public static partial class Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Position the cursor before the first record in the table. A
|
||||
/// subsequent move next will position the cursor on the first
|
||||
/// record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The table to position.</param>
|
||||
public static void MoveBeforeFirst(JET_SESID sesid, JET_TABLEID tableid)
|
||||
{
|
||||
Api.TryMoveFirst(sesid, tableid);
|
||||
Api.TryMovePrevious(sesid, tableid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Position the cursor after the last record in the table. A
|
||||
/// subsequent move previous will position the cursor on the
|
||||
/// last record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The table to position.</param>
|
||||
public static void MoveAfterLast(JET_SESID sesid, JET_TABLEID tableid)
|
||||
{
|
||||
Api.TryMoveLast(sesid, tableid);
|
||||
Api.TryMoveNext(sesid, tableid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to navigate through an index. If the navigation succeeds this
|
||||
/// method returns true. If there is no record to navigate to this
|
||||
/// method returns false; an exception will be thrown for other errors.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to position.</param>
|
||||
/// <param name="move">The direction to move in.</param>
|
||||
/// <param name="grbit">Move options.</param>
|
||||
/// <returns>True if the move was successful.</returns>
|
||||
public static bool TryMove(JET_SESID sesid, JET_TABLEID tableid, JET_Move move, MoveGrbit grbit)
|
||||
{
|
||||
var err = (JET_err)Impl.JetMove(sesid, tableid, (int)move, grbit);
|
||||
if (JET_err.NoCurrentRecord == err)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Api.Check((int)err);
|
||||
Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to move to the first record in the table. If the table is empty this
|
||||
/// returns false, if a different error is encountered an exception is thrown.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to position.</param>
|
||||
/// <returns>True if the move was successful.</returns>
|
||||
public static bool TryMoveFirst(JET_SESID sesid, JET_TABLEID tableid)
|
||||
{
|
||||
return TryMove(sesid, tableid, JET_Move.First, MoveGrbit.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to move to the last record in the table. If the table is empty this
|
||||
/// returns false, if a different error is encountered an exception is thrown.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to position.</param>
|
||||
/// <returns>True if the move was successful.</returns>
|
||||
public static bool TryMoveLast(JET_SESID sesid, JET_TABLEID tableid)
|
||||
{
|
||||
return TryMove(sesid, tableid, JET_Move.Last, MoveGrbit.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to move to the next record in the table. If there is not a next record
|
||||
/// this returns false, if a different error is encountered an exception is thrown.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to position.</param>
|
||||
/// <returns>True if the move was successful.</returns>
|
||||
public static bool TryMoveNext(JET_SESID sesid, JET_TABLEID tableid)
|
||||
{
|
||||
return TryMove(sesid, tableid, JET_Move.Next, MoveGrbit.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to move to the previous record in the table. If there is not a previous record
|
||||
/// this returns false, if a different error is encountered an exception is thrown.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to position.</param>
|
||||
/// <returns>True if the move was successful.</returns>
|
||||
public static bool TryMovePrevious(JET_SESID sesid, JET_TABLEID tableid)
|
||||
{
|
||||
return TryMove(sesid, tableid, JET_Move.Previous, MoveGrbit.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Efficiently positions a cursor to an index entry that matches the search
|
||||
/// criteria specified by the search key in that cursor and the specified
|
||||
/// inequality. A search key must have been previously constructed using JetMakeKey.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to position.</param>
|
||||
/// <param name="grbit">Seek option.</param>
|
||||
/// <returns>True if a record matching the criteria was found.</returns>
|
||||
public static bool TrySeek(JET_SESID sesid, JET_TABLEID tableid, SeekGrbit grbit)
|
||||
{
|
||||
var err = (JET_err)Impl.JetSeek(sesid, tableid, grbit);
|
||||
if (JET_err.RecordNotFound == err)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Api.Check((int)err);
|
||||
Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Temporarily limits the set of index entries that the cursor can walk using
|
||||
/// JetMove to those starting from the current index entry and ending at the index
|
||||
/// entry that matches the search criteria specified by the search key in that cursor
|
||||
/// and the specified bound criteria. A search key must have been previously constructed
|
||||
/// using JetMakeKey. Returns true if the index range is non-empty, false otherwise.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to position.</param>
|
||||
/// <param name="grbit">Seek option.</param>
|
||||
/// <returns>True if the seek was successful.</returns>
|
||||
public static bool TrySetIndexRange(JET_SESID sesid, JET_TABLEID tableid, SetIndexRangeGrbit grbit)
|
||||
{
|
||||
var err = (JET_err)Impl.JetSetIndexRange(sesid, tableid, grbit);
|
||||
if (JET_err.NoCurrentRecord == err)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Api.Check((int)err);
|
||||
Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an index range created with <see cref="JetSetIndexRange"/> or
|
||||
/// <see cref="TrySetIndexRange"/>. If no index range is present this
|
||||
/// method does nothing.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to remove the index range on.</param>
|
||||
public static void ResetIndexRange(JET_SESID sesid, JET_TABLEID tableid)
|
||||
{
|
||||
var err = (JET_err)Impl.JetSetIndexRange(sesid, tableid, SetIndexRangeGrbit.RangeRemove);
|
||||
if (JET_err.InvalidOperation == err)
|
||||
{
|
||||
// this error is expected if there isn't currently an index range
|
||||
return;
|
||||
}
|
||||
|
||||
Api.Check((int)err);
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Intersect a group of index ranges and return the bookmarks of the records which are found
|
||||
/// in all the index ranges.
|
||||
/// Also see <see cref="JetIntersectIndexes"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableids">
|
||||
/// The tableids to use. Each tableid must be from a different index on the same table and
|
||||
/// have an active index range. Use <see cref="JetSetIndexRange"/>
|
||||
/// to create an index range.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The bookmarks of the records which are found in all the index ranges. The bookmarks
|
||||
/// are returned in primary key order.
|
||||
/// </returns>
|
||||
public static IEnumerable<byte[]> IntersectIndexes(JET_SESID sesid, params JET_TABLEID[] tableids)
|
||||
{
|
||||
if (null == tableids)
|
||||
{
|
||||
throw new ArgumentNullException("tableids");
|
||||
}
|
||||
|
||||
var ranges = new JET_INDEXRANGE[tableids.Length];
|
||||
for (int i = 0; i < tableids.Length; ++i)
|
||||
{
|
||||
ranges[i] = new JET_INDEXRANGE { tableid = tableids[i] };
|
||||
}
|
||||
|
||||
return new GenericEnumerable<byte[]>(() => new IntersectIndexesEnumerator(sesid, ranges));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Positions a cursor to an index entry for the record that is associated with
|
||||
/// the specified bookmark. The bookmark can be used with any index defined over
|
||||
/// a table. The bookmark for a record can be retrieved using <see cref="JetGetBookmark"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to position.</param>
|
||||
/// <param name="bookmark">The bookmark used to position the cursor.</param>
|
||||
/// <param name="bookmarkSize">The size of the bookmark.</param>
|
||||
/// <returns>True if a record matching the bookmark was found.</returns>
|
||||
public static bool TryGotoBookmark(JET_SESID sesid, JET_TABLEID tableid, byte[] bookmark, int bookmarkSize)
|
||||
{
|
||||
var err = (JET_err)Impl.JetGotoBookmark(sesid, tableid, bookmark, bookmarkSize);
|
||||
|
||||
// Return false if the record no longer exists.
|
||||
if (JET_err.RecordDeleted == err)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return false if there is no entry for this record on the current (secondary) index.
|
||||
if (JET_err.NoCurrentRecord == err)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Api.Check((int)err);
|
||||
Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
1263
WelsonJS.Toolkit/EsentInterop/NativeMethods.cs
Normal file
1263
WelsonJS.Toolkit/EsentInterop/NativeMethods.cs
Normal file
File diff suppressed because it is too large
Load Diff
53
WelsonJS.Toolkit/EsentInterop/ObjectInfoFlags.cs
Normal file
53
WelsonJS.Toolkit/EsentInterop/ObjectInfoFlags.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ObjectInfoFlags.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Flags for ESENT objects (tables). Used in <see cref="JET_OBJECTINFO"/>.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ObjectInfoFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// Default options.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Object is for internal use only.
|
||||
/// </summary>
|
||||
System = -2147483648, // 0x80000000
|
||||
// It's possible to use bit shift to avoid triggering fxcop CA2217.
|
||||
// System = (long)0x1L << 31, // 0x80000000;
|
||||
// (http://social.msdn.microsoft.com/Forums/en-US/vstscode/thread/a44aa5c1-c62a-46b7-8009-dc46ba21ba93)
|
||||
// But we don't want to change the type of the enum to a long.
|
||||
|
||||
/// <summary>
|
||||
/// Table's DDL is fixed.
|
||||
/// </summary>
|
||||
TableFixedDDL = 0x40000000,
|
||||
|
||||
/// <summary>
|
||||
/// Table's DDL is inheritable.
|
||||
/// </summary>
|
||||
TableTemplate = 0x20000000,
|
||||
|
||||
/// <summary>
|
||||
/// Table's DDL is inherited from a template table.
|
||||
/// </summary>
|
||||
TableDerived = 0x10000000,
|
||||
|
||||
/// <summary>
|
||||
/// Fixed or variable columns in derived tables (so that fixed or variable
|
||||
/// columns can be added to the template in the future).
|
||||
/// Used in conjunction with <see cref="TableTemplate"/>.
|
||||
/// </summary>
|
||||
TableNoFixedVarColumnsInDerivedTables = 0x04000000,
|
||||
}
|
||||
}
|
||||
52
WelsonJS.Toolkit/EsentInterop/ObsoleteApi.cs
Normal file
52
WelsonJS.Toolkit/EsentInterop/ObsoleteApi.cs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="ObsoleteApi.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// API members that are marked as obsolete.
|
||||
/// </summary>
|
||||
public static partial class Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves information about indexes on a table.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="dbid">The database to use.</param>
|
||||
/// <param name="tablename">The name of the table to retrieve index information about.</param>
|
||||
/// <param name="ignored">This parameter is ignored.</param>
|
||||
/// <param name="indexlist">Filled in with information about indexes on the table.</param>
|
||||
[Obsolete("Use the overload that takes a JET_IdxInfo parameter, passing in JET_IdxInfo.List")]
|
||||
public static void JetGetIndexInfo(
|
||||
JET_SESID sesid,
|
||||
JET_DBID dbid,
|
||||
string tablename,
|
||||
string ignored,
|
||||
out JET_INDEXLIST indexlist)
|
||||
{
|
||||
Api.JetGetIndexInfo(sesid, dbid, tablename, ignored, out indexlist, JET_IdxInfo.List);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves information about indexes on a table.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The table to retrieve index information about.</param>
|
||||
/// <param name="indexname">This parameter is ignored.</param>
|
||||
/// <param name="indexlist">Filled in with information about indexes on the table.</param>
|
||||
[Obsolete("Use the overload that takes a JET_IdxInfo parameter, passing in JET_IdxInfo.List")]
|
||||
public static void JetGetTableIndexInfo(
|
||||
JET_SESID sesid,
|
||||
JET_TABLEID tableid,
|
||||
string indexname,
|
||||
out JET_INDEXLIST indexlist)
|
||||
{
|
||||
Api.JetGetTableIndexInfo(sesid, tableid, indexname, out indexlist, JET_IdxInfo.List);
|
||||
}
|
||||
}
|
||||
}
|
||||
44
WelsonJS.Toolkit/EsentInterop/OnlineMaintenanceHelpers.cs
Normal file
44
WelsonJS.Toolkit/EsentInterop/OnlineMaintenanceHelpers.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="OnlineMaintenanceHelpers.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Microsoft.Isam.Esent.Interop.Implementation;
|
||||
|
||||
/// <summary>
|
||||
/// Helper methods for the ESENT API. These methods deal with database
|
||||
/// meta-data.
|
||||
/// </summary>
|
||||
public static partial class Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Starts and stops database defragmentation tasks that improves data
|
||||
/// organization within a database.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use for the call.</param>
|
||||
/// <param name="dbid">The database to be defragmented.</param>
|
||||
/// <param name="tableName">
|
||||
/// Under some options defragmentation is performed for the entire database described by the given
|
||||
/// database ID, and other options (such as <see cref="Windows7.Windows7Grbits.DefragmentBTree"/>) require
|
||||
/// the name of the table to defragment.
|
||||
/// </param>
|
||||
/// <param name="grbit">Defragmentation options.</param>
|
||||
/// <returns>A warning code.</returns>
|
||||
/// <seealso cref="Api.JetDefragment"/>
|
||||
public static JET_wrn Defragment(
|
||||
JET_SESID sesid,
|
||||
JET_DBID dbid,
|
||||
string tableName,
|
||||
DefragGrbit grbit)
|
||||
{
|
||||
return Api.Check(Impl.Defragment(sesid, dbid, tableName, grbit));
|
||||
}
|
||||
}
|
||||
}
|
||||
1172
WelsonJS.Toolkit/EsentInterop/RetrieveColumnHelpers.cs
Normal file
1172
WelsonJS.Toolkit/EsentInterop/RetrieveColumnHelpers.cs
Normal file
File diff suppressed because it is too large
Load Diff
50
WelsonJS.Toolkit/EsentInterop/Server2003Api.cs
Normal file
50
WelsonJS.Toolkit/EsentInterop/Server2003Api.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Server2003Api.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Server2003
|
||||
{
|
||||
/// <summary>
|
||||
/// APIs that have been added to the Windows Server 2003 version of ESENT.
|
||||
/// </summary>
|
||||
public static class Server2003Api
|
||||
{
|
||||
#if !MANAGEDESENT_ON_WSA
|
||||
/// <summary>
|
||||
/// Notifies the engine that it can resume normal IO operations after a
|
||||
/// freeze period ended with a failed snapshot.
|
||||
/// </summary>
|
||||
/// <param name="snapid">Identifier of the snapshot session.</param>
|
||||
/// <param name="grbit">Options for this call.</param>
|
||||
public static void JetOSSnapshotAbort(JET_OSSNAPID snapid, SnapshotAbortGrbit grbit)
|
||||
{
|
||||
Api.Check(Api.Impl.JetOSSnapshotAbort(snapid, grbit));
|
||||
}
|
||||
#endif // !MANAGEDESENT_ON_WSA
|
||||
|
||||
/// <summary>
|
||||
/// The JetUpdate function performs an update operation including inserting a new row into
|
||||
/// a table or updating an existing row. Deleting a table row is performed by calling
|
||||
/// <see cref="Api.JetDelete"/>.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session which started the update.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="bookmark">Returns the bookmark of the updated record. This can be null.</param>
|
||||
/// <param name="bookmarkSize">The size of the bookmark buffer.</param>
|
||||
/// <param name="actualBookmarkSize">Returns the actual size of the bookmark.</param>
|
||||
/// <param name="grbit">Update options.</param>
|
||||
/// <remarks>
|
||||
/// JetUpdate is the final step in performing an insert or an update. The update is begun by
|
||||
/// calling <see cref="Api.JetPrepareUpdate"/> and then by calling
|
||||
/// <see cref="Api.JetSetColumn(JET_SESID,JET_TABLEID,JET_COLUMNID,byte[],int,SetColumnGrbit,JET_SETINFO)"/>
|
||||
/// one or more times to set the record state. Finally, <see cref="JetUpdate2"/>
|
||||
/// is called to complete the update operation. Indexes are updated only by JetUpdate or and not during JetSetColumn.
|
||||
/// </remarks>
|
||||
public static void JetUpdate2(JET_SESID sesid, JET_TABLEID tableid, byte[] bookmark, int bookmarkSize, out int actualBookmarkSize, UpdateGrbit grbit)
|
||||
{
|
||||
Api.Check(Api.Impl.JetUpdate2(sesid, tableid, bookmark, bookmarkSize, out actualBookmarkSize, grbit));
|
||||
}
|
||||
}
|
||||
}
|
||||
108
WelsonJS.Toolkit/EsentInterop/Server2003Grbits.cs
Normal file
108
WelsonJS.Toolkit/EsentInterop/Server2003Grbits.cs
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Server2003Grbits.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Server2003
|
||||
{
|
||||
using System;
|
||||
|
||||
#if !MANAGEDESENT_ON_WSA // Not exposed in MSDK
|
||||
/// <summary>
|
||||
/// Options for <see cref="Server2003Api.JetOSSnapshotAbort"/>.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum SnapshotAbortGrbit
|
||||
{
|
||||
/// <summary>
|
||||
/// Default options.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
}
|
||||
#endif // !MANAGEDESENT_ON_WSA
|
||||
|
||||
/// <summary>
|
||||
/// Options for <see cref="Server2003Api.JetUpdate2"/>.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum UpdateGrbit
|
||||
{
|
||||
/// <summary>
|
||||
/// Default options.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
#if !MANAGEDESENT_ON_WSA // Not exposed in MSDK
|
||||
/// <summary>
|
||||
/// This flag causes the update to return an error if the update would
|
||||
/// not have been possible in the Windows 2000 version of ESE, which
|
||||
/// enforced a smaller maximum number of multi-valued column instances
|
||||
/// in each record than later versions of ESE. This is important only
|
||||
/// for applications that wish to replicate data between applications
|
||||
/// hosted on Windows 2000 and applications hosted on Windows
|
||||
/// 2003, or later versions of ESE. It should not be necessary for most
|
||||
/// applications.
|
||||
/// </summary>
|
||||
[Obsolete("Only needed for legacy replication applications.")]
|
||||
CheckESE97Compatibility = 0x1,
|
||||
#endif // !MANAGEDESENT_ON_WSA
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Grbits that have been added to the Windows Server 2003 version of ESENT.
|
||||
/// </summary>
|
||||
public static class Server2003Grbits
|
||||
{
|
||||
/// <summary>
|
||||
/// Delete all indexes with unicode columns.
|
||||
/// </summary>
|
||||
public const AttachDatabaseGrbit DeleteUnicodeIndexes = (AttachDatabaseGrbit)0x400;
|
||||
|
||||
/// <summary>
|
||||
/// When the escrow-update column reaches a value of zero (after all
|
||||
/// versions are resolve), the record will be deleted. A common use for
|
||||
/// a column that can be finalized is to use it as a reference count
|
||||
/// field, and when the field reaches zero the record gets deleted. A
|
||||
/// Delete-on-zero column must be an escrow update / <see cref="ColumndefGrbit.ColumnEscrowUpdate"/>
|
||||
/// column. ColumnDeleteOnZero cannot be used with ColumnFinalize.
|
||||
/// ColumnDeleteOnZero cannot be used with user defined default columns.
|
||||
/// </summary>
|
||||
public const ColumndefGrbit ColumnDeleteOnZero = (ColumndefGrbit)0x20000;
|
||||
|
||||
/// <summary>
|
||||
/// This option requests that the temporary table only be created if the
|
||||
/// temporary table manager can use the implementation optimized for
|
||||
/// intermediate query results. If any characteristic of the temporary
|
||||
/// table would prevent the use of this optimization then the operation
|
||||
/// will fail with JET_errCannotMaterializeForwardOnlySort. A side effect
|
||||
/// of this option is to allow the temporary table to contain records
|
||||
/// with duplicate index keys. See <see cref="TempTableGrbit.Unique"/>
|
||||
/// for more information.
|
||||
/// </summary>
|
||||
public const TempTableGrbit ForwardOnly = (TempTableGrbit)0x40;
|
||||
|
||||
/// <summary>
|
||||
/// If a given column is not present in the record and it has a user
|
||||
/// defined default value then no column value will be returned.
|
||||
/// This option will prevent the callback that computes the user defined
|
||||
/// default value for the column from being called when enumerating
|
||||
/// the values for that column.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This option is only available for Windows Server 2003 SP1 and later
|
||||
/// operating systems.
|
||||
/// </remarks>
|
||||
public const EnumerateColumnsGrbit EnumerateIgnoreUserDefinedDefault = (EnumerateColumnsGrbit)0x00100000;
|
||||
|
||||
/// <summary>
|
||||
/// All transactions previously committed by any session that have not
|
||||
/// yet been flushed to the transaction log file will be flushed immediately.
|
||||
/// This API will wait until the transactions have been flushed before
|
||||
/// returning to the caller. This option may be used even if the session
|
||||
/// is not currently in a transaction. This option cannot be used in
|
||||
/// combination with any other option.
|
||||
/// </summary>
|
||||
public const CommitTransactionGrbit WaitAllLevel0Commit = (CommitTransactionGrbit)0x8;
|
||||
}
|
||||
}
|
||||
24
WelsonJS.Toolkit/EsentInterop/Server2003Param.cs
Normal file
24
WelsonJS.Toolkit/EsentInterop/Server2003Param.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Server2003Param.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Server2003
|
||||
{
|
||||
/// <summary>
|
||||
/// System parameters that have been added to the Windows Server 2003 version of ESENT.
|
||||
/// </summary>
|
||||
public static class Server2003Param
|
||||
{
|
||||
/// <summary>
|
||||
/// The full path to each database is persisted in the transaction logs
|
||||
/// at run time. Ordinarily, these databases must remain at the original
|
||||
/// location for transaction replay to function correctly. This
|
||||
/// parameter can be used to force crash recovery or a restore operation
|
||||
/// to look for the databases referenced in the transaction log in the
|
||||
/// specified folder.
|
||||
/// </summary>
|
||||
public const JET_param AlternateDatabaseRecoveryPath = (JET_param)113;
|
||||
}
|
||||
}
|
||||
89
WelsonJS.Toolkit/EsentInterop/Session.cs
Normal file
89
WelsonJS.Toolkit/EsentInterop/Session.cs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Session.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System.Globalization;
|
||||
|
||||
/// <summary>
|
||||
/// A class that encapsulates a JET_SESID in a disposable object.
|
||||
/// </summary>
|
||||
public class Session : EsentResource
|
||||
{
|
||||
/// <summary>
|
||||
/// The underlying JET_SESID.
|
||||
/// </summary>
|
||||
private JET_SESID sesid;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Session class. A new
|
||||
/// JET_SESSION is allocated from the given instance.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance to start the session in.</param>
|
||||
public Session(JET_INSTANCE instance)
|
||||
{
|
||||
Api.JetBeginSession(instance, out this.sesid, null, null);
|
||||
this.ResourceWasAllocated();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the JET_SESID that this session contains.
|
||||
/// </summary>
|
||||
public JET_SESID JetSesid
|
||||
{
|
||||
get
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
return this.sesid;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion operator from a Session to a JET_SESID. This
|
||||
/// allows a Session to be used with APIs which expect a JET_SESID.
|
||||
/// </summary>
|
||||
/// <param name="session">The session to convert.</param>
|
||||
/// <returns>The JET_SESID of the session.</returns>
|
||||
public static implicit operator JET_SESID(Session session)
|
||||
{
|
||||
return session.JetSesid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="Session"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="Session"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "Session (0x{0:x})", this.sesid.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Terminate the session.
|
||||
/// </summary>
|
||||
public void End()
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
this.ReleaseResource();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free the underlying JET_SESID.
|
||||
/// </summary>
|
||||
protected override void ReleaseResource()
|
||||
{
|
||||
if (!this.sesid.IsInvalid)
|
||||
{
|
||||
Api.JetEndSession(this.JetSesid, EndSessionGrbit.None);
|
||||
}
|
||||
|
||||
this.sesid = JET_SESID.Nil;
|
||||
this.ResourceWasReleased();
|
||||
}
|
||||
}
|
||||
}
|
||||
544
WelsonJS.Toolkit/EsentInterop/SetColumnHelpers.cs
Normal file
544
WelsonJS.Toolkit/EsentInterop/SetColumnHelpers.cs
Normal file
|
|
@ -0,0 +1,544 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="SetColumnHelpers.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.Serialization;
|
||||
#if MANAGEDESENT_SUPPORTS_SERIALIZATION
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
#endif
|
||||
using System.Text;
|
||||
using Microsoft.Isam.Esent.Interop.Vista;
|
||||
using Microsoft.Isam.Esent.Interop.Windows10;
|
||||
|
||||
/// <summary>
|
||||
/// Helper methods for the ESENT API. These do data conversion for
|
||||
/// setting columns.
|
||||
/// </summary>
|
||||
public static partial class Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
/// <param name="encoding">The encoding used to convert the string.</param>
|
||||
public static void SetColumn(
|
||||
JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, string data, Encoding encoding)
|
||||
{
|
||||
SetColumn(sesid, tableid, columnid, data, encoding, SetColumnGrbit.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
/// <param name="encoding">The encoding used to convert the string.</param>
|
||||
/// <param name="grbit">SetColumn options.</param>
|
||||
public static void SetColumn(
|
||||
JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, string data, Encoding encoding, SetColumnGrbit grbit)
|
||||
{
|
||||
CheckEncodingIsValid(encoding);
|
||||
|
||||
if (null == data)
|
||||
{
|
||||
JetSetColumn(sesid, tableid, columnid, null, 0, grbit, null);
|
||||
}
|
||||
else if (0 == data.Length)
|
||||
{
|
||||
JetSetColumn(sesid, tableid, columnid, null, 0, grbit | SetColumnGrbit.ZeroLength, null);
|
||||
}
|
||||
else if (Encoding.Unicode == encoding)
|
||||
{
|
||||
// Optimization for setting Unicode strings.
|
||||
unsafe
|
||||
{
|
||||
fixed (char* buffer = data)
|
||||
{
|
||||
JetSetColumn(
|
||||
sesid,
|
||||
tableid,
|
||||
columnid,
|
||||
new IntPtr(buffer),
|
||||
checked(data.Length * sizeof(char)),
|
||||
grbit,
|
||||
null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (encoding.GetMaxByteCount(data.Length) <= Caches.ColumnCache.BufferSize)
|
||||
{
|
||||
#if MANAGEDESENT_ON_WSA
|
||||
// Encoding.GetBytes(char*, int, byte*, int) overload is missing in new Windows UI.
|
||||
// So we can't use the ColumnCache. We'll just use a different GetBytes() overload.
|
||||
byte[] buffer = encoding.GetBytes(data);
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* bytes = buffer)
|
||||
{
|
||||
JetSetColumn(sesid, tableid, columnid, new IntPtr(bytes), buffer.Length, grbit, null);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// The encoding output will fix in a cached buffer. Get one to avoid
|
||||
// more memory allocations.
|
||||
byte[] buffer = null;
|
||||
|
||||
try
|
||||
{
|
||||
buffer = Caches.ColumnCache.Allocate();
|
||||
unsafe
|
||||
{
|
||||
fixed (char* chars = data)
|
||||
fixed (byte* bytes = buffer)
|
||||
{
|
||||
int dataSize = encoding.GetBytes(chars, data.Length, bytes, buffer.Length);
|
||||
JetSetColumn(sesid, tableid, columnid, new IntPtr(bytes), dataSize, grbit, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
Caches.ColumnCache.Free(ref buffer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] bytes = encoding.GetBytes(data);
|
||||
JetSetColumn(sesid, tableid, columnid, bytes, bytes.Length, grbit, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data)
|
||||
{
|
||||
SetColumn(sesid, tableid, columnid, data, SetColumnGrbit.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
/// <param name="grbit">SetColumn options.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, SetColumnGrbit grbit)
|
||||
{
|
||||
int dataLength = (null == data) ? 0 : data.Length;
|
||||
SetColumn(sesid, tableid, columnid, data, dataLength, grbit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
/// <param name="dataSize">The size of data to set.</param>
|
||||
/// <param name="grbit">SetColumn options.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, int dataSize, SetColumnGrbit grbit)
|
||||
{
|
||||
if ((null != data) && (0 == data.Length))
|
||||
{
|
||||
grbit |= SetColumnGrbit.ZeroLength;
|
||||
}
|
||||
|
||||
if (data == null && dataSize > 0)
|
||||
{
|
||||
throw new ArgumentException(string.Format("data is null, but dataSize is: {0}", dataSize));
|
||||
}
|
||||
|
||||
if (data != null && data.Length < dataSize)
|
||||
{
|
||||
throw new ArgumentException(string.Format("data.Length is less, than dataSize: data.Length={0}, dataSize={1}", data.Length, dataSize));
|
||||
}
|
||||
|
||||
JetSetColumn(sesid, tableid, columnid, data, dataSize, grbit, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, bool data)
|
||||
{
|
||||
byte b = data ? (byte)0xff : (byte)0x0;
|
||||
SetColumn(sesid, tableid, columnid, b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(byte);
|
||||
var pointer = new IntPtr(&data);
|
||||
JetSetColumn(sesid, tableid, columnid, pointer, DataSize, SetColumnGrbit.None, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, short data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(short);
|
||||
var pointer = new IntPtr(&data);
|
||||
JetSetColumn(sesid, tableid, columnid, pointer, DataSize, SetColumnGrbit.None, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, int data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(int);
|
||||
var pointer = new IntPtr(&data);
|
||||
JetSetColumn(sesid, tableid, columnid, pointer, DataSize, SetColumnGrbit.None, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, long data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(long);
|
||||
var pointer = new IntPtr(&data);
|
||||
JetSetColumn(sesid, tableid, columnid, pointer, DataSize, SetColumnGrbit.None, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, Guid data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = 16; // sizeof(Guid) isn't a compile-time constant
|
||||
var pointer = new IntPtr(&data);
|
||||
JetSetColumn(sesid, tableid, columnid, pointer, DataSize, SetColumnGrbit.None, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, DateTime data)
|
||||
{
|
||||
SetColumn(sesid, tableid, columnid, data.ToOADate());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, float data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(float);
|
||||
var pointer = new IntPtr(&data);
|
||||
JetSetColumn(sesid, tableid, columnid, pointer, DataSize, SetColumnGrbit.None, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, double data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(double);
|
||||
var pointer = new IntPtr(&data);
|
||||
JetSetColumn(sesid, tableid, columnid, pointer, DataSize, SetColumnGrbit.None, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform atomic addition on an Int32 column. The column must be of type
|
||||
/// <see cref="JET_coltyp.Long"/>. This function allows multiple sessions to update the
|
||||
/// same record concurrently without conflicts.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method wraps <see cref="JetEscrowUpdate"/>.
|
||||
/// </remarks>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update.</param>
|
||||
/// <param name="columnid">The column to update. This must be an escrow-updatable column.</param>
|
||||
/// <param name="delta">The delta to apply to the column.</param>
|
||||
/// <returns>The current value of the column as stored in the database (versioning is ignored).</returns>
|
||||
public static int EscrowUpdate(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, int delta)
|
||||
{
|
||||
var previousValue = new byte[sizeof(int)];
|
||||
int actualPreviousValueLength;
|
||||
JetEscrowUpdate(
|
||||
sesid,
|
||||
tableid,
|
||||
columnid,
|
||||
BitConverter.GetBytes(delta),
|
||||
sizeof(int),
|
||||
previousValue,
|
||||
previousValue.Length,
|
||||
out actualPreviousValueLength,
|
||||
EscrowUpdateGrbit.None);
|
||||
Debug.Assert(
|
||||
previousValue.Length == actualPreviousValueLength,
|
||||
"Unexpected previous value length. Expected an Int32");
|
||||
return BitConverter.ToInt32(previousValue, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform atomic addition on an Int64 column. The column must be of type
|
||||
/// <see cref="VistaColtyp.LongLong"/>. This function allows multiple sessions to update the
|
||||
/// same record concurrently without conflicts.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method wraps <see cref="JetEscrowUpdate"/>.
|
||||
/// </remarks>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update.</param>
|
||||
/// <param name="columnid">The column to update. This must be an escrow-updatable column.</param>
|
||||
/// <param name="delta">The delta to apply to the column.</param>
|
||||
/// <returns>The current value of the column as stored in the database (versioning is ignored).</returns>
|
||||
public static long EscrowUpdate(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, long delta)
|
||||
{
|
||||
var previousValue = new byte[sizeof(long)];
|
||||
int actualPreviousValueLength;
|
||||
JetEscrowUpdate(
|
||||
sesid,
|
||||
tableid,
|
||||
columnid,
|
||||
BitConverter.GetBytes(delta),
|
||||
sizeof(long),
|
||||
previousValue,
|
||||
previousValue.Length,
|
||||
out actualPreviousValueLength,
|
||||
EscrowUpdateGrbit.None);
|
||||
Debug.Assert(
|
||||
previousValue.Length == actualPreviousValueLength,
|
||||
"Unexpected previous value length. Expected an Int64");
|
||||
return BitConverter.ToInt64(previousValue, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
[CLSCompliant(false)]
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, ushort data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(ushort);
|
||||
var pointer = new IntPtr(&data);
|
||||
JetSetColumn(sesid, tableid, columnid, pointer, DataSize, SetColumnGrbit.None, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
[CLSCompliant(false)]
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, uint data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(uint);
|
||||
var pointer = new IntPtr(&data);
|
||||
JetSetColumn(sesid, tableid, columnid, pointer, DataSize, SetColumnGrbit.None, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modifies a single column value in a modified record to be inserted or to
|
||||
/// update the current record.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="columnid">The columnid to set.</param>
|
||||
/// <param name="data">The data to set.</param>
|
||||
[CLSCompliant(false)]
|
||||
public static void SetColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, ulong data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
const int DataSize = sizeof(ulong);
|
||||
var pointer = new IntPtr(&data);
|
||||
JetSetColumn(sesid, tableid, columnid, pointer, DataSize, SetColumnGrbit.None, null);
|
||||
}
|
||||
}
|
||||
|
||||
#if MANAGEDESENT_SUPPORTS_SERIALIZATION
|
||||
/// <summary>
|
||||
/// Write a serialized form of an object to a column.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The table to write to. An update should be prepared.</param>
|
||||
/// <param name="columnid">The column to write to.</param>
|
||||
/// <param name="value">The object to write. The object must be serializable.</param>
|
||||
[SuppressMessage("Exchange.Security", "EX0043:DoNotUseBinarySoapFormatter", Justification = "Suppress warning in current code base.The usage has already been verified.")]
|
||||
public static void SerializeObjectToColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, object value)
|
||||
{
|
||||
if (null == value)
|
||||
{
|
||||
Api.SetColumn(sesid, tableid, columnid, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var stream = new ColumnStream(sesid, tableid, columnid))
|
||||
{
|
||||
var serializer = new BinaryFormatter
|
||||
{
|
||||
Context = new StreamingContext(StreamingContextStates.Persistence)
|
||||
};
|
||||
serializer.Serialize(stream, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Sets columns from ColumnValue objects.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The cursor to update. An update should be prepared.</param>
|
||||
/// <param name="values">The values to set.</param>
|
||||
public static void SetColumns(JET_SESID sesid, JET_TABLEID tableid, params ColumnValue[] values)
|
||||
{
|
||||
if (null == values)
|
||||
{
|
||||
throw new ArgumentNullException("values");
|
||||
}
|
||||
|
||||
if (0 == values.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("values", values.Length, "must have at least one value");
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
NATIVE_SETCOLUMN* nativeSetcolumns = stackalloc NATIVE_SETCOLUMN[values.Length];
|
||||
Api.Check(values[0].SetColumns(sesid, tableid, values, nativeSetcolumns, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the given encoding is valid for setting/retrieving data. Only
|
||||
/// the ASCII and Unicode encodings are allowed. An <see cref="ArgumentOutOfRangeException"/>
|
||||
/// is thrown if the encoding isn't valid.
|
||||
/// </summary>
|
||||
/// <param name="encoding">The encoding to check.</param>
|
||||
private static void CheckEncodingIsValid(Encoding encoding)
|
||||
{
|
||||
#if MANAGEDESENT_ON_CORECLR
|
||||
string webName = encoding.WebName;
|
||||
if (webName != "utf-8" && webName != "utf-16")
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
"encoding", webName, "Invalid Encoding type. Only Unicode (utf-8 and utf-16) encodings are allowed.");
|
||||
}
|
||||
#else
|
||||
const int AsciiCodePage = 20127; // from MSDN
|
||||
const int UnicodeCodePage = 1200; // from MSDN
|
||||
int codePage = encoding.CodePage;
|
||||
if ((AsciiCodePage != codePage) && (UnicodeCodePage != codePage))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
"encoding", codePage, "Invalid Encoding type. Only ASCII and Unicode encodings are allowed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
78
WelsonJS.Toolkit/EsentInterop/Settings.StyleCop
Normal file
78
WelsonJS.Toolkit/EsentInterop/Settings.StyleCop
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<StyleCopSettings Version="105">
|
||||
<GlobalSettings>
|
||||
<BooleanProperty Name="WriteCache">False</BooleanProperty>
|
||||
<CollectionProperty Name="RecognizedWords">
|
||||
<Value>api</Value>
|
||||
<Value>coltyp</Value>
|
||||
<Value>columndef</Value>
|
||||
<Value>columnid</Value>
|
||||
<Value>dbid</Value>
|
||||
<Value>dll</Value>
|
||||
<Value>ese</Value>
|
||||
<Value>esent</Value>
|
||||
<Value>grbit</Value>
|
||||
<Value>grbits</Value>
|
||||
<Value>interop</Value>
|
||||
<Value>itag</Value>
|
||||
<Value>lgpos</Value>
|
||||
<Value>param</Value>
|
||||
<Value>preread</Value>
|
||||
<Value>sesid</Value>
|
||||
<Value>tableid</Value>
|
||||
</CollectionProperty>
|
||||
</GlobalSettings>
|
||||
<Analyzers>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.NamingRules">
|
||||
<AnalyzerSettings>
|
||||
<CollectionProperty Name="Hungarian">
|
||||
<Value>c</Value>
|
||||
<Value>cb</Value>
|
||||
<Value>dw</Value>
|
||||
<Value>f</Value>
|
||||
<Value>h</Value>
|
||||
<Value>ib</Value>
|
||||
<Value>l</Value>
|
||||
<Value>p</Value>
|
||||
<Value>pv</Value>
|
||||
<Value>rg</Value>
|
||||
<Value>sz</Value>
|
||||
<Value>ul</Value>
|
||||
<Value>w</Value>
|
||||
</CollectionProperty>
|
||||
</AnalyzerSettings>
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
|
||||
<Rules>
|
||||
<Rule Name="DocumentationTextMustBeginWithACapitalLetter">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">True</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="DocumentationTextMustEndWithAPeriod">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">True</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
<Rule Name="FileHeaderFileNameDocumentationMustMatchTypeName">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings>
|
||||
<StringProperty Name="CompanyName">Microsoft Corporation</StringProperty>
|
||||
<StringProperty Name="Copyright">Copyright (c) Microsoft Corporation.</StringProperty>
|
||||
</AnalyzerSettings>
|
||||
</Analyzer>
|
||||
<Analyzer AnalyzerId="StyleCop.CSharp.MaintainabilityRules">
|
||||
<Rules>
|
||||
<Rule Name="FileMayOnlyContainASingleNamespace">
|
||||
<RuleSettings>
|
||||
<BooleanProperty Name="Enabled">False</BooleanProperty>
|
||||
</RuleSettings>
|
||||
</Rule>
|
||||
</Rules>
|
||||
<AnalyzerSettings />
|
||||
</Analyzer>
|
||||
</Analyzers>
|
||||
</StyleCopSettings>
|
||||
166
WelsonJS.Toolkit/EsentInterop/StringCache.cs
Normal file
166
WelsonJS.Toolkit/EsentInterop/StringCache.cs
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="StringCache.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class that helps cache strings.
|
||||
/// </summary>
|
||||
internal static class StringCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Don't cache strings whose length is longer than this.
|
||||
/// </summary>
|
||||
private const int MaxLengthToCache = 128;
|
||||
|
||||
/// <summary>
|
||||
/// Number of converted strings to hash.
|
||||
/// </summary>
|
||||
private const int NumCachedBoxedValues = 1031;
|
||||
|
||||
/// <summary>
|
||||
/// Cached string values.
|
||||
/// </summary>
|
||||
private static readonly string[] CachedStrings = new string[NumCachedBoxedValues];
|
||||
|
||||
/// <summary>
|
||||
/// Return the interned version of a string, or the original
|
||||
/// string if it isn't interned.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to try to intern.</param>
|
||||
/// <returns>An interned copy of the string or the original string.</returns>
|
||||
public static string TryToIntern(string s)
|
||||
{
|
||||
#if MANAGEDESENT_ON_WSA
|
||||
// new Windows UI Core CLR does not support string interning.
|
||||
return s;
|
||||
#else
|
||||
return string.IsInterned(s) ?? s;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a byte array to a string.
|
||||
/// </summary>
|
||||
/// <param name="value">The bytes to convert.</param>
|
||||
/// <param name="startIndex">The starting index of the data to convert.</param>
|
||||
/// <param name="count">The number of bytes to convert.</param>
|
||||
/// <returns>A string converted from the data.</returns>
|
||||
public static string GetString(byte[] value, int startIndex, int count)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* data = value)
|
||||
{
|
||||
char* chars = (char*)(data + startIndex);
|
||||
return GetString(chars, 0, count / sizeof(char));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a char array to a string, using a cached value if possible.
|
||||
/// </summary>
|
||||
/// <param name="value">The characters to convert.</param>
|
||||
/// <param name="startIndex">The starting index of the data to convert.</param>
|
||||
/// <param name="count">The number of characters to convert.</param>
|
||||
/// <returns>A string converted from the data.</returns>
|
||||
private static unsafe string GetString(char* value, int startIndex, int count)
|
||||
{
|
||||
string s;
|
||||
|
||||
if (0 == count)
|
||||
{
|
||||
s = string.Empty;
|
||||
}
|
||||
else if (count < MaxLengthToCache)
|
||||
{
|
||||
uint hash = CalculateHash(value, startIndex, count);
|
||||
int index = unchecked((int)(hash % NumCachedBoxedValues));
|
||||
s = CachedStrings[index];
|
||||
if (null == s || !AreEqual(s, value, startIndex, count))
|
||||
{
|
||||
s = CreateNewString(value, startIndex, count);
|
||||
CachedStrings[index] = s;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s = CreateNewString(value, startIndex, count);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the hash of a string.
|
||||
/// </summary>
|
||||
/// <param name="value">The characters to hash.</param>
|
||||
/// <param name="startIndex">The starting index of the data to hash.</param>
|
||||
/// <param name="count">The number of characters to hash.</param>
|
||||
/// <returns>The hash value of the data.</returns>
|
||||
private static unsafe uint CalculateHash(char* value, int startIndex, int count)
|
||||
{
|
||||
uint hash = 0;
|
||||
unchecked
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
hash ^= value[startIndex + i];
|
||||
hash *= 33;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if a string matches a char array..
|
||||
/// </summary>
|
||||
/// <param name="s">The string to compare against.</param>
|
||||
/// <param name="value">The characters.</param>
|
||||
/// <param name="startIndex">The starting index of the data.</param>
|
||||
/// <param name="count">The number of characters.</param>
|
||||
/// <returns>True if the string matches the char array.</returns>
|
||||
private static unsafe bool AreEqual(string s, char* value, int startIndex, int count)
|
||||
{
|
||||
if (s.Length != count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unchecked
|
||||
{
|
||||
for (int i = 0; i < s.Length; ++i)
|
||||
{
|
||||
if (s[i] != value[startIndex + i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a char array to a string.
|
||||
/// </summary>
|
||||
/// <param name="value">The characters to convert.</param>
|
||||
/// <param name="startIndex">The starting index of the data to convert.</param>
|
||||
/// <param name="count">The number of characters to convert.</param>
|
||||
/// <returns>A string converted from the data.</returns>
|
||||
private static unsafe string CreateNewString(char* value, int startIndex, int count)
|
||||
{
|
||||
// Encoding.Unicode.GetString copies the data to an array of chars and then
|
||||
// makes a string from it, copying the data twice. Use the more efficient
|
||||
// char* constructor.
|
||||
return new string(value, startIndex, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
128
WelsonJS.Toolkit/EsentInterop/StringColumnValue.cs
Normal file
128
WelsonJS.Toolkit/EsentInterop/StringColumnValue.cs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="StringColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A Unicode string column value.
|
||||
/// </summary>
|
||||
public class StringColumnValue : ColumnValue
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal value.
|
||||
/// </summary>
|
||||
private string internalValue;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last set or retrieved value of the column. The
|
||||
/// value is returned as a generic object.
|
||||
/// </summary>
|
||||
public override object ValueAsObject
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.Value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the column. Use <see cref="Api.SetColumns"/> to update a
|
||||
/// record with the column value.
|
||||
/// </summary>
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.internalValue;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.internalValue = value;
|
||||
this.Error = value == null ? JET_wrn.ColumnNull : JET_wrn.Success;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte length of a column value, which is zero if column is null, otherwise
|
||||
/// it matches the byte length of the string value. The byte length is determined in
|
||||
/// assumption of two bytes per character.
|
||||
/// </summary>
|
||||
public override int Length
|
||||
{
|
||||
get { return this.Value != null ? this.Value.Length * sizeof(char) : 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a string representation of this object.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
if (null != this.Value)
|
||||
{
|
||||
fixed (void* buffer = this.Value)
|
||||
{
|
||||
return this.SetColumns(
|
||||
sesid, tableid, columnValues, nativeColumns, i, buffer, checked(this.Value.Length * sizeof(char)), true);
|
||||
}
|
||||
}
|
||||
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, null, 0, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Value = StringCache.GetString(value, startIndex, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
487
WelsonJS.Toolkit/EsentInterop/SystemParameters.cs
Normal file
487
WelsonJS.Toolkit/EsentInterop/SystemParameters.cs
Normal file
|
|
@ -0,0 +1,487 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="SystemParameters.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using Microsoft.Isam.Esent.Interop.Vista;
|
||||
using Microsoft.Isam.Esent.Interop.Windows7;
|
||||
|
||||
/// <summary>
|
||||
/// This class provides static properties to set and get
|
||||
/// global ESENT system parameters.
|
||||
/// </summary>
|
||||
public static partial class SystemParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum size of the database page cache. The size
|
||||
/// is in database pages. If this parameter is left to its default value, then the
|
||||
/// maximum size of the cache will be set to the size of physical memory when JetInit
|
||||
/// is called.
|
||||
/// </summary>
|
||||
public static int CacheSizeMax
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetIntegerParameter(JET_param.CacheSizeMax);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetIntegerParameter(JET_param.CacheSizeMax, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the database cache in pages. By default the
|
||||
/// database cache will automatically tune its size, setting this property
|
||||
/// to a non-zero value will cause the cache to adjust itself to the target
|
||||
/// size.
|
||||
/// </summary>
|
||||
public static int CacheSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetIntegerParameter(JET_param.CacheSize);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetIntegerParameter(JET_param.CacheSize, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the database pages, in bytes.
|
||||
/// </summary>
|
||||
public static int DatabasePageSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetIntegerParameter(JET_param.DatabasePageSize);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetIntegerParameter(JET_param.DatabasePageSize, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum size of the database page cache, in database pages.
|
||||
/// </summary>
|
||||
public static int CacheSizeMin
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetIntegerParameter(JET_param.CacheSizeMin);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetIntegerParameter(JET_param.CacheSizeMin, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets how many database file I/Os can be queued
|
||||
/// per-disk in the host operating system at one time. A larger value
|
||||
/// for this parameter can significantly help the performance of a large
|
||||
/// database application.
|
||||
/// </summary>
|
||||
public static int OutstandingIOMax
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetIntegerParameter(JET_param.OutstandingIOMax);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetIntegerParameter(JET_param.OutstandingIOMax, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the threshold at which the database page cache begins evicting pages from the
|
||||
/// cache to make room for pages that are not cached. When the number of page buffers in the cache
|
||||
/// drops below this threshold then a background process will be started to replenish that pool
|
||||
/// of available buffers. This threshold is always relative to the maximum cache size as set by
|
||||
/// JET_paramCacheSizeMax. This threshold must also always be less than the stop threshold as
|
||||
/// set by JET_paramStopFlushThreshold.
|
||||
/// <para>
|
||||
/// The distance height of the start threshold will determine the response time that the database
|
||||
/// page cache must have to produce available buffers before the application needs them. A high
|
||||
/// start threshold will give the background process more time to react. However, a high start
|
||||
/// threshold implies a higher stop threshold and that will reduce the effective size of the
|
||||
/// database page cache.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public static int StartFlushThreshold
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetIntegerParameter(JET_param.StartFlushThreshold);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetIntegerParameter(JET_param.StartFlushThreshold, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the threshold at which the database page cache ends evicting pages from the cache to make
|
||||
/// room for pages that are not cached. When the number of page buffers in the cache rises above
|
||||
/// this threshold then the background process that was started to replenish that pool of available
|
||||
/// buffers is stopped. This threshold is always relative to the maximum cache size as set by
|
||||
/// JET_paramCacheSizeMax. This threshold must also always be greater than the start threshold
|
||||
/// as set by JET_paramStartFlushThreshold.
|
||||
/// <para>
|
||||
/// The distance between the start threshold and the stop threshold affects the efficiency with
|
||||
/// which database pages are flushed by the background process. A larger gap will make it
|
||||
/// more likely that writes to neighboring pages may be combined. However, a high stop
|
||||
/// threshold will reduce the effective size of the database page cache.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public static int StopFlushThreshold
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetIntegerParameter(JET_param.StopFlushThreshold);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetIntegerParameter(JET_param.StopFlushThreshold, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum number of instances that can be created.
|
||||
/// </summary>
|
||||
public static int MaxInstances
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetIntegerParameter(JET_param.MaxInstances);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetIntegerParameter(JET_param.MaxInstances, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the detail level of eventlog messages that are emitted
|
||||
/// to the eventlog by the database engine. Higher numbers will result
|
||||
/// in more detailed eventlog messages.
|
||||
/// </summary>
|
||||
public static int EventLoggingLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetIntegerParameter(JET_param.EventLoggingLevel);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetIntegerParameter(JET_param.EventLoggingLevel, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum key size. This depends on the Esent version and database
|
||||
/// page size.
|
||||
/// </summary>
|
||||
public static int KeyMost
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
return GetIntegerParameter(VistaParam.KeyMost);
|
||||
}
|
||||
|
||||
// All pre-Vista versions of Esent have 255 byte keys
|
||||
return 255;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum number of components in a sort or index key.
|
||||
/// </summary>
|
||||
public static int ColumnsKeyMost
|
||||
{
|
||||
get
|
||||
{
|
||||
return Api.Impl.Capabilities.ColumnsKeyMost;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum size of a bookmark. <seealso cref="Api.JetGetBookmark"/>.
|
||||
/// </summary>
|
||||
public static int BookmarkMost
|
||||
{
|
||||
get
|
||||
{
|
||||
// This correctly returns 256 on pre-Vista systems
|
||||
return KeyMost + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lv chunks size. This depends on the database page size.
|
||||
/// </summary>
|
||||
public static int LVChunkSizeMost
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EsentVersion.SupportsWindows7Features)
|
||||
{
|
||||
return GetIntegerParameter(Windows7Param.LVChunkSizeMost);
|
||||
}
|
||||
|
||||
// Can't retrieve the size directly, determine it from the database page size
|
||||
const int ColumnLvPageOverhead = 82;
|
||||
return GetIntegerParameter(JET_param.DatabasePageSize) - ColumnLvPageOverhead;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value specifying the default values for the
|
||||
/// entire set of system parameters. When this parameter is set to
|
||||
/// a specific configuration, all system parameter values are reset
|
||||
/// to their default values for that configuration. If the
|
||||
/// configuration is set for a specific instance then global system
|
||||
/// parameters will not be reset to their default values.
|
||||
/// Small Configuration (0): The database engine is optimized for memory use.
|
||||
/// Legacy Configuration (1): The database engine has its traditional defaults.
|
||||
/// <para>
|
||||
/// Supported on Windows Vista and up. Ignored on Windows XP and
|
||||
/// Windows Server 2003.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public static int Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
return GetIntegerParameter(VistaParam.Configuration);
|
||||
}
|
||||
|
||||
// return the legacy configuration value
|
||||
return 1;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
SetIntegerParameter(VistaParam.Configuration, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the database engine accepts
|
||||
/// or rejects changes to a subset of the system parameters. This
|
||||
/// parameter is used in conjunction with <see cref="Configuration"/> to
|
||||
/// prevent some system parameters from being set away from the selected
|
||||
/// configuration's defaults.
|
||||
/// <para>
|
||||
/// Supported on Windows Vista and up. Ignored on Windows XP and
|
||||
/// Windows Server 2003.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public static bool EnableAdvanced
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
return GetBoolParameter(VistaParam.EnableAdvanced);
|
||||
}
|
||||
|
||||
// older versions always allow advanced settings
|
||||
return true;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
SetBoolParameter(VistaParam.EnableAdvanced, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets backwards compatibility with the file naming conventions of earlier releases of the database engine.
|
||||
/// </summary>
|
||||
public static int LegacyFileNames
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
return GetIntegerParameter(VistaParam.LegacyFileNames);
|
||||
}
|
||||
|
||||
// return the legacy LegacyFileNames value
|
||||
return 1;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
SetIntegerParameter(VistaParam.LegacyFileNames, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value encoding what to do with exceptions generated within JET.
|
||||
/// </summary>
|
||||
public static JET_ExceptionAction ExceptionAction
|
||||
{
|
||||
get
|
||||
{
|
||||
return (JET_ExceptionAction)GetIntegerParameter(JET_param.ExceptionAction);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetIntegerParameter(JET_param.ExceptionAction, (int)value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the database engine should
|
||||
/// use the OS file cache for all managed files.
|
||||
/// </summary>
|
||||
public static bool EnableFileCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
return GetBoolParameter(VistaParam.EnableFileCache);
|
||||
}
|
||||
|
||||
// Pre-Vista versions of do not implement this.
|
||||
return false;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
SetBoolParameter(VistaParam.EnableFileCache, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the database engine should
|
||||
/// use memory mapped file I/O for database files.
|
||||
/// </summary>
|
||||
public static bool EnableViewCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
return GetBoolParameter(VistaParam.EnableViewCache);
|
||||
}
|
||||
|
||||
// Pre-Vista versions of do not implement this.
|
||||
return false;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (EsentVersion.SupportsVistaFeatures)
|
||||
{
|
||||
SetBoolParameter(VistaParam.EnableViewCache, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a system parameter which is a string.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to set.</param>
|
||||
/// <param name="value">The value to set.</param>
|
||||
private static void SetStringParameter(JET_param param, string value)
|
||||
{
|
||||
Api.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, param, 0, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a system parameter which is a string.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to get.</param>
|
||||
/// <returns>The value of the parameter.</returns>
|
||||
private static string GetStringParameter(JET_param param)
|
||||
{
|
||||
int ignored = 0;
|
||||
string value;
|
||||
Api.JetGetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, param, ref ignored, out value, 1024);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a system parameter which is an integer.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to set.</param>
|
||||
/// <param name="value">The value to set.</param>
|
||||
private static void SetIntegerParameter(JET_param param, int value)
|
||||
{
|
||||
Api.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, param, value, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a system parameter which is an integer.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to get.</param>
|
||||
/// <returns>The value of the parameter.</returns>
|
||||
private static int GetIntegerParameter(JET_param param)
|
||||
{
|
||||
int value = 0;
|
||||
string ignored;
|
||||
Api.JetGetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, param, ref value, out ignored, 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a system parameter which is a boolean.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to set.</param>
|
||||
/// <param name="value">The value to set.</param>
|
||||
private static void SetBoolParameter(JET_param param, bool value)
|
||||
{
|
||||
int setting = value ? 1 : 0;
|
||||
Api.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, param, setting, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a system parameter which is a boolean.
|
||||
/// </summary>
|
||||
/// <param name="param">The parameter to get.</param>
|
||||
/// <returns>The value of the parameter.</returns>
|
||||
private static bool GetBoolParameter(JET_param param)
|
||||
{
|
||||
int value = 0;
|
||||
string ignored;
|
||||
Api.JetGetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, param, ref value, out ignored, 0);
|
||||
return value != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
114
WelsonJS.Toolkit/EsentInterop/Table.cs
Normal file
114
WelsonJS.Toolkit/EsentInterop/Table.cs
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Table.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// A class that encapsulates a JET_TABLEID in a disposable object.
|
||||
/// This opens an existing table. To create a table use the
|
||||
/// JetCreateTable method.
|
||||
/// </summary>
|
||||
public class Table : EsentResource
|
||||
{
|
||||
/// <summary>
|
||||
/// The session used to open the table.
|
||||
/// </summary>
|
||||
private JET_SESID sesid;
|
||||
|
||||
/// <summary>
|
||||
/// The underlying JET_TABLEID.
|
||||
/// </summary>
|
||||
private JET_TABLEID tableid;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the table.
|
||||
/// </summary>
|
||||
private string name;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Table class. The table is
|
||||
/// opened from the given database.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="dbid">The database to open the table in.</param>
|
||||
/// <param name="name">The name of the table.</param>
|
||||
/// <param name="grbit">JetOpenTable options.</param>
|
||||
public Table(JET_SESID sesid, JET_DBID dbid, string name, OpenTableGrbit grbit)
|
||||
{
|
||||
this.sesid = sesid;
|
||||
this.name = name;
|
||||
Api.JetOpenTable(this.sesid, dbid, this.name, null, 0, grbit, out this.tableid);
|
||||
this.ResourceWasAllocated();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of this table.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the JET_TABLEID that this table contains.
|
||||
/// </summary>
|
||||
public JET_TABLEID JetTableid
|
||||
{
|
||||
get
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
return this.tableid;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion operator from a Table to a JET_TABLEID. This
|
||||
/// allows a Table to be used with APIs which expect a JET_TABLEID.
|
||||
/// </summary>
|
||||
/// <param name="table">The table to convert.</param>
|
||||
/// <returns>The JET_TABLEID of the table.</returns>
|
||||
public static implicit operator JET_TABLEID(Table table)
|
||||
{
|
||||
return table.JetTableid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="Table"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="Table"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the table.
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
this.ReleaseResource();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free the underlying JET_TABLEID.
|
||||
/// </summary>
|
||||
protected override void ReleaseResource()
|
||||
{
|
||||
Api.JetCloseTable(this.sesid, this.tableid);
|
||||
this.sesid = JET_SESID.Nil;
|
||||
this.tableid = JET_TABLEID.Nil;
|
||||
this.name = null;
|
||||
this.ResourceWasReleased();
|
||||
}
|
||||
}
|
||||
}
|
||||
53
WelsonJS.Toolkit/EsentInterop/TableColumnInfoEnumerator.cs
Normal file
53
WelsonJS.Toolkit/EsentInterop/TableColumnInfoEnumerator.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="TableColumnInfoEnumerator.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerate columns in a table specified by dbid and name.
|
||||
/// </summary>
|
||||
internal sealed class TableColumnInfoEnumerator : ColumnInfoEnumerator
|
||||
{
|
||||
/// <summary>
|
||||
/// The database containing the table.
|
||||
/// </summary>
|
||||
private readonly JET_DBID dbid;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the table.
|
||||
/// </summary>
|
||||
private readonly string tablename;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TableColumnInfoEnumerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="sesid">
|
||||
/// The session to use.
|
||||
/// </param>
|
||||
/// <param name="dbid">
|
||||
/// The database containing the table.
|
||||
/// </param>
|
||||
/// <param name="tablename">
|
||||
/// The name of the table.
|
||||
/// </param>
|
||||
public TableColumnInfoEnumerator(JET_SESID sesid, JET_DBID dbid, string tablename) : base(sesid)
|
||||
{
|
||||
this.dbid = dbid;
|
||||
this.tablename = tablename;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open the table to be enumerated. This should set <see cref="TableEnumerator{T}.TableidToEnumerate"/>.
|
||||
/// </summary>
|
||||
protected override void OpenTable()
|
||||
{
|
||||
JET_COLUMNLIST columnlist;
|
||||
Api.JetGetColumnInfo(this.Sesid, this.dbid, this.tablename, string.Empty, out columnlist);
|
||||
this.Columnlist = columnlist;
|
||||
this.TableidToEnumerate = this.Columnlist.tableid;
|
||||
}
|
||||
}
|
||||
}
|
||||
167
WelsonJS.Toolkit/EsentInterop/TableEnumerator.cs
Normal file
167
WelsonJS.Toolkit/EsentInterop/TableEnumerator.cs
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="TableEnumerator.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for enumerators that walk a table.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type returned by the enumerator.</typeparam>
|
||||
internal abstract class TableEnumerator<T> : IEnumerator<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// True if we are at the end of the table.
|
||||
/// </summary>
|
||||
private bool isAtEnd;
|
||||
|
||||
/// <summary>
|
||||
/// True if we need to move to the first record in the table.
|
||||
/// </summary>
|
||||
private bool moveToFirst = true;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TableEnumerator{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="sesid">
|
||||
/// The session to use.
|
||||
/// </param>
|
||||
protected TableEnumerator(JET_SESID sesid)
|
||||
{
|
||||
this.Sesid = sesid;
|
||||
this.TableidToEnumerate = JET_TABLEID.Nil;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current entry.
|
||||
/// </summary>
|
||||
public T Current { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current entry.
|
||||
/// </summary>
|
||||
object IEnumerator.Current
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return this.Current; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the session used for the enumeration.
|
||||
/// </summary>
|
||||
protected JET_SESID Sesid { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the table being enumerated.
|
||||
/// </summary>
|
||||
protected JET_TABLEID TableidToEnumerate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resets the enumerator. The next call to MoveNext will move
|
||||
/// to the first entry.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
this.isAtEnd = false;
|
||||
this.moveToFirst = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes of any resources the enumerator is using.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.CloseTable();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move to the next entry.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// True if an entry was found, false otherwise.
|
||||
/// </returns>
|
||||
public bool MoveNext()
|
||||
{
|
||||
// Moving to the end is sticky (until Reset is called)
|
||||
if (this.isAtEnd)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.TableidToEnumerate.IsInvalid)
|
||||
{
|
||||
Debug.Assert(this.moveToFirst, "Table has not been opened so moveToFirst should be true");
|
||||
this.OpenTable();
|
||||
}
|
||||
|
||||
bool needMoveNext = true;
|
||||
if (this.moveToFirst)
|
||||
{
|
||||
if (!Api.TryMoveFirst(this.Sesid, this.TableidToEnumerate))
|
||||
{
|
||||
this.isAtEnd = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.moveToFirst = false;
|
||||
needMoveNext = false;
|
||||
}
|
||||
|
||||
while (needMoveNext || this.SkipCurrent())
|
||||
{
|
||||
if (!Api.TryMoveNext(this.Sesid, this.TableidToEnumerate))
|
||||
{
|
||||
this.isAtEnd = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
needMoveNext = false;
|
||||
}
|
||||
|
||||
this.Current = this.GetCurrent();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open the table to be enumerated. This should set <see cref="TableidToEnumerate"/>.
|
||||
/// </summary>
|
||||
protected abstract void OpenTable();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entry the cursor is currently positioned on.
|
||||
/// </summary>
|
||||
/// <returns>The entry the cursor is currently positioned on.</returns>
|
||||
protected abstract T GetCurrent();
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the current entry in the table being enumerated should
|
||||
/// be skipped (not returned). By default this is false.
|
||||
/// </summary>
|
||||
/// <returns>True if the current entry should be skipped.</returns>
|
||||
protected virtual bool SkipCurrent()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the table being enumerated.
|
||||
/// </summary>
|
||||
protected virtual void CloseTable()
|
||||
{
|
||||
if (!this.TableidToEnumerate.IsInvalid)
|
||||
{
|
||||
Api.JetCloseTable(this.Sesid, this.TableidToEnumerate);
|
||||
}
|
||||
|
||||
this.TableidToEnumerate = JET_TABLEID.Nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
WelsonJS.Toolkit/EsentInterop/TableIndexInfoEnumerator.cs
Normal file
70
WelsonJS.Toolkit/EsentInterop/TableIndexInfoEnumerator.cs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="TableIndexInfoEnumerator.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerate columns in a table specified by dbid and name.
|
||||
/// </summary>
|
||||
internal sealed class TableIndexInfoEnumerator : IndexInfoEnumerator
|
||||
{
|
||||
/// <summary>
|
||||
/// The database containing the table.
|
||||
/// </summary>
|
||||
private readonly JET_DBID dbid;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the table.
|
||||
/// </summary>
|
||||
private readonly string tablename;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TableIndexInfoEnumerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="sesid">
|
||||
/// The session to use.
|
||||
/// </param>
|
||||
/// <param name="dbid">
|
||||
/// The database containing the table.
|
||||
/// </param>
|
||||
/// <param name="tablename">
|
||||
/// The name of the table.
|
||||
/// </param>
|
||||
public TableIndexInfoEnumerator(JET_SESID sesid, JET_DBID dbid, string tablename)
|
||||
: base(sesid)
|
||||
{
|
||||
this.dbid = dbid;
|
||||
this.tablename = tablename;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open the table to be enumerated. This should set <see cref="TableEnumerator{T}.TableidToEnumerate"/>.
|
||||
/// </summary>
|
||||
protected override void OpenTable()
|
||||
{
|
||||
JET_INDEXLIST indexlist;
|
||||
Api.JetGetIndexInfo(this.Sesid, this.dbid, this.tablename, string.Empty, out indexlist, JET_IdxInfo.List);
|
||||
this.Indexlist = indexlist;
|
||||
this.TableidToEnumerate = this.Indexlist.tableid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves information about indexes on a table.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="indexname">The name of the index.</param>
|
||||
/// <param name="result">Filled in with information about indexes on the table.</param>
|
||||
/// <param name="infoLevel">The type of information to retrieve.</param>
|
||||
protected override void GetIndexInfo(
|
||||
JET_SESID sesid,
|
||||
string indexname,
|
||||
out string result,
|
||||
JET_IdxInfo infoLevel)
|
||||
{
|
||||
Api.JetGetIndexInfo(sesid, this.dbid, this.tablename, indexname, out result, infoLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
79
WelsonJS.Toolkit/EsentInterop/TableNameEnumerator.cs
Normal file
79
WelsonJS.Toolkit/EsentInterop/TableNameEnumerator.cs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="TableNameEnumerator.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System.Text;
|
||||
using Microsoft.Isam.Esent.Interop.Implementation;
|
||||
|
||||
/// <summary>
|
||||
/// Enumerate the names of tables in a database.
|
||||
/// </summary>
|
||||
internal sealed class TableNameEnumerator : TableEnumerator<string>
|
||||
{
|
||||
/// <summary>
|
||||
/// The database containing the tables.
|
||||
/// </summary>
|
||||
private readonly JET_DBID dbid;
|
||||
|
||||
/// <summary>
|
||||
/// Object list containing information about tables.
|
||||
/// </summary>
|
||||
private JET_OBJECTLIST objectlist;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TableNameEnumerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="sesid">
|
||||
/// The session to use.
|
||||
/// </param>
|
||||
/// <param name="dbid">
|
||||
/// The database to get the table names from.
|
||||
/// </param>
|
||||
public TableNameEnumerator(JET_SESID sesid, JET_DBID dbid) : base(sesid)
|
||||
{
|
||||
this.dbid = dbid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open the table to be enumerated. This should set <see cref="TableEnumerator{T}.TableidToEnumerate"/>.
|
||||
/// </summary>
|
||||
protected override void OpenTable()
|
||||
{
|
||||
Api.JetGetObjectInfo(this.Sesid, this.dbid, out this.objectlist);
|
||||
this.TableidToEnumerate = this.objectlist.tableid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the current entry in the table being enumerated should
|
||||
/// be skipped (not returned). Here we are skipping system tables.
|
||||
/// </summary>
|
||||
/// <returns>True if the current entry should be skipped.</returns>
|
||||
protected override bool SkipCurrent()
|
||||
{
|
||||
int flags = (int)Api.RetrieveColumnAsInt32(this.Sesid, this.TableidToEnumerate, this.objectlist.columnidflags);
|
||||
return ObjectInfoFlags.System == ((ObjectInfoFlags)flags & ObjectInfoFlags.System);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entry the cursor is currently positioned on.
|
||||
/// </summary>
|
||||
/// <returns>The entry the cursor is currently positioned on.</returns>
|
||||
protected override string GetCurrent()
|
||||
{
|
||||
// If we use the wide API (Vista+), then the temp table will be in UTF-16.
|
||||
Encoding encodingOfTextColumns = EsentVersion.SupportsVistaFeatures ? Encoding.Unicode : LibraryHelpers.EncodingASCII;
|
||||
|
||||
string name = Api.RetrieveColumnAsString(
|
||||
this.Sesid,
|
||||
this.TableidToEnumerate,
|
||||
this.objectlist.columnidobjectname,
|
||||
encodingOfTextColumns,
|
||||
RetrieveColumnGrbit.None);
|
||||
return StringCache.TryToIntern(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
44
WelsonJS.Toolkit/EsentInterop/TableidColumnInfoEnumerator.cs
Normal file
44
WelsonJS.Toolkit/EsentInterop/TableidColumnInfoEnumerator.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="TableidColumnInfoEnumerator.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerate columns in a table specified by a tableid.
|
||||
/// </summary>
|
||||
internal sealed class TableidColumnInfoEnumerator : ColumnInfoEnumerator
|
||||
{
|
||||
/// <summary>
|
||||
/// The table to get the column information from.
|
||||
/// </summary>
|
||||
private readonly JET_TABLEID tableid;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TableidColumnInfoEnumerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="sesid">
|
||||
/// The session to use.
|
||||
/// </param>
|
||||
/// <param name="tableid">
|
||||
/// The table to get column information from.
|
||||
/// </param>
|
||||
public TableidColumnInfoEnumerator(JET_SESID sesid, JET_TABLEID tableid) : base(sesid)
|
||||
{
|
||||
this.tableid = tableid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open the table to be enumerated. This should set <see cref="TableEnumerator{T}.TableidToEnumerate"/>.
|
||||
/// </summary>
|
||||
protected override void OpenTable()
|
||||
{
|
||||
JET_COLUMNLIST columnlist;
|
||||
Api.JetGetTableColumnInfo(this.Sesid, this.tableid, string.Empty, out columnlist);
|
||||
this.Columnlist = columnlist;
|
||||
this.TableidToEnumerate = this.Columnlist.tableid;
|
||||
}
|
||||
}
|
||||
}
|
||||
61
WelsonJS.Toolkit/EsentInterop/TableidIndexInfoEnumerator.cs
Normal file
61
WelsonJS.Toolkit/EsentInterop/TableidIndexInfoEnumerator.cs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="TableidIndexInfoEnumerator.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerate columns in a table specified by a tableid.
|
||||
/// </summary>
|
||||
internal sealed class TableidIndexInfoEnumerator : IndexInfoEnumerator
|
||||
{
|
||||
/// <summary>
|
||||
/// The table to get the column information from.
|
||||
/// </summary>
|
||||
private readonly JET_TABLEID tableid;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TableidIndexInfoEnumerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="sesid">
|
||||
/// The session to use.
|
||||
/// </param>
|
||||
/// <param name="tableid">
|
||||
/// The table to get column information from.
|
||||
/// </param>
|
||||
public TableidIndexInfoEnumerator(JET_SESID sesid, JET_TABLEID tableid)
|
||||
: base(sesid)
|
||||
{
|
||||
this.tableid = tableid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open the table to be enumerated. This should set <see cref="TableEnumerator{T}.TableidToEnumerate"/>.
|
||||
/// </summary>
|
||||
protected override void OpenTable()
|
||||
{
|
||||
JET_INDEXLIST indexlist;
|
||||
Api.JetGetTableIndexInfo(this.Sesid, this.tableid, string.Empty, out indexlist, JET_IdxInfo.List);
|
||||
this.Indexlist = indexlist;
|
||||
this.TableidToEnumerate = this.Indexlist.tableid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves information about indexes on a table.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="indexname">The name of the index.</param>
|
||||
/// <param name="result">Filled in with information about indexes on the table.</param>
|
||||
/// <param name="infoLevel">The type of information to retrieve.</param>
|
||||
protected override void GetIndexInfo(
|
||||
JET_SESID sesid,
|
||||
string indexname,
|
||||
out string result,
|
||||
JET_IdxInfo infoLevel)
|
||||
{
|
||||
Api.JetGetTableIndexInfo(sesid, this.tableid, indexname, out result, infoLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
160
WelsonJS.Toolkit/EsentInterop/Transaction.cs
Normal file
160
WelsonJS.Toolkit/EsentInterop/Transaction.cs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Transaction.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using Microsoft.Isam.Esent.Interop.Windows8;
|
||||
|
||||
/// <summary>
|
||||
/// A class that encapsulates a transaction on a JET_SESID.
|
||||
/// </summary>
|
||||
public class Transaction : EsentResource
|
||||
{
|
||||
/// <summary>
|
||||
/// The underlying JET_SESID.
|
||||
/// </summary>
|
||||
private readonly JET_SESID sesid;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Transaction class. This automatically
|
||||
/// begins a transaction. The transaction will be rolled back if
|
||||
/// not explicitly committed.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to start the transaction for.</param>
|
||||
public Transaction(JET_SESID sesid)
|
||||
{
|
||||
this.sesid = sesid;
|
||||
this.Begin();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current transaction level of the
|
||||
/// <see cref="Transaction"/>.
|
||||
/// Requires Win10.
|
||||
/// </summary>
|
||||
public int TransactionLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
int transactionLevel = -1;
|
||||
if (EsentVersion.SupportsWindows10Features)
|
||||
{
|
||||
Windows8Api.JetGetSessionParameter(
|
||||
this.sesid,
|
||||
Windows10.Windows10Sesparam.TransactionLevel,
|
||||
out transactionLevel);
|
||||
}
|
||||
|
||||
return transactionLevel;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this object is currently in a
|
||||
/// transaction.
|
||||
/// </summary>
|
||||
public bool IsInTransaction
|
||||
{
|
||||
get
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
return this.HasResource;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="Transaction"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="Transaction"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "Transaction (0x{0:x})", this.sesid.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begin a transaction. This object should not currently be
|
||||
/// in a transaction.
|
||||
/// </summary>
|
||||
public void Begin()
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
if (this.IsInTransaction)
|
||||
{
|
||||
throw new InvalidOperationException("Already in a transaction");
|
||||
}
|
||||
|
||||
Api.JetBeginTransaction(this.sesid);
|
||||
this.ResourceWasAllocated();
|
||||
Debug.Assert(this.IsInTransaction, "Begin finished, but object isn't in a transaction");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commit a transaction. This object should be in a transaction.
|
||||
/// </summary>
|
||||
/// <param name="grbit">JetCommitTransaction options.</param>
|
||||
public void Commit(CommitTransactionGrbit grbit)
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
if (!this.IsInTransaction)
|
||||
{
|
||||
throw new InvalidOperationException("Not in a transaction");
|
||||
}
|
||||
|
||||
Api.JetCommitTransaction(this.sesid, grbit);
|
||||
this.ResourceWasReleased();
|
||||
Debug.Assert(!this.IsInTransaction, "Commit finished, but object is still in a transaction");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commit a transaction. This object should be in a transaction.
|
||||
/// </summary>
|
||||
/// <param name="grbit">JetCommitTransaction options.</param>
|
||||
/// <param name="durableCommit">Duration for committing lazy transactions.</param>
|
||||
/// <param name="commitId">Commit-id for this commit record.</param>
|
||||
public void Commit(CommitTransactionGrbit grbit, TimeSpan durableCommit, out JET_COMMIT_ID commitId)
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
if (!this.IsInTransaction)
|
||||
{
|
||||
throw new InvalidOperationException("Not in a transaction");
|
||||
}
|
||||
|
||||
Windows8.Windows8Api.JetCommitTransaction2(this.sesid, grbit, durableCommit, out commitId);
|
||||
this.ResourceWasReleased();
|
||||
Debug.Assert(!this.IsInTransaction, "Commit finished, but object is still in a transaction");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rollback a transaction. This object should be in a transaction.
|
||||
/// </summary>
|
||||
public void Rollback()
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
if (!this.IsInTransaction)
|
||||
{
|
||||
throw new InvalidOperationException("Not in a transaction");
|
||||
}
|
||||
|
||||
Api.JetRollback(this.sesid, RollbackTransactionGrbit.None);
|
||||
this.ResourceWasReleased();
|
||||
Debug.Assert(!this.IsInTransaction, "Commit finished, but object is still in a transaction");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the transaction is being disposed while active.
|
||||
/// This should rollback the transaction.
|
||||
/// </summary>
|
||||
protected override void ReleaseResource()
|
||||
{
|
||||
this.Rollback();
|
||||
}
|
||||
}
|
||||
}
|
||||
1142
WelsonJS.Toolkit/EsentInterop/Types.cs
Normal file
1142
WelsonJS.Toolkit/EsentInterop/Types.cs
Normal file
File diff suppressed because it is too large
Load Diff
70
WelsonJS.Toolkit/EsentInterop/UInt16ColumnValue.cs
Normal file
70
WelsonJS.Toolkit/EsentInterop/UInt16ColumnValue.cs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="UInt16ColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ushort"/> column value.
|
||||
/// </summary>
|
||||
[CLSCompliant(false)]
|
||||
public class UInt16ColumnValue : ColumnValueOfStruct<ushort>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return sizeof(ushort); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
var data = this.Value.GetValueOrDefault();
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(ushort), this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
this.Value = BitConverter.ToUInt16(value, startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
70
WelsonJS.Toolkit/EsentInterop/UInt32ColumnValue.cs
Normal file
70
WelsonJS.Toolkit/EsentInterop/UInt32ColumnValue.cs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="UInt32ColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="uint"/> column value.
|
||||
/// </summary>
|
||||
[CLSCompliant(false)]
|
||||
public class UInt32ColumnValue : ColumnValueOfStruct<uint>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return sizeof(uint); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
var data = this.Value.GetValueOrDefault();
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(uint), this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
this.Value = BitConverter.ToUInt32(value, startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
70
WelsonJS.Toolkit/EsentInterop/UInt64ColumnValue.cs
Normal file
70
WelsonJS.Toolkit/EsentInterop/UInt64ColumnValue.cs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="UInt64ColumnValue.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ulong"/> column value.
|
||||
/// </summary>
|
||||
[CLSCompliant(false)]
|
||||
public class UInt64ColumnValue : ColumnValueOfStruct<ulong>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size of the value in the column. This returns 0 for
|
||||
/// variable sized columns (i.e. binary and string).
|
||||
/// </summary>
|
||||
protected override int Size
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return sizeof(ulong); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursive SetColumns method for data pinning. This populates the buffer and
|
||||
/// calls the inherited SetColumns method.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The table to set the columns in. An update should be prepared.
|
||||
/// </param>
|
||||
/// <param name="columnValues">
|
||||
/// Column values to set.
|
||||
/// </param>
|
||||
/// <param name="nativeColumns">
|
||||
/// Structures to put the pinned data in.
|
||||
/// </param>
|
||||
/// <param name="i">Offset of this object in the array.</param>
|
||||
/// <returns>An error code.</returns>
|
||||
internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN* nativeColumns, int i)
|
||||
{
|
||||
var data = this.Value.GetValueOrDefault();
|
||||
return this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(ulong), this.Value.HasValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object.
|
||||
/// </summary>
|
||||
/// <param name="value">An array of bytes.</param>
|
||||
/// <param name="startIndex">The starting position within the bytes.</param>
|
||||
/// <param name="count">The number of bytes to decode.</param>
|
||||
/// <param name="err">The error returned from ESENT.</param>
|
||||
protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err)
|
||||
{
|
||||
if (JET_wrn.ColumnNull == (JET_wrn)err)
|
||||
{
|
||||
this.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckDataCount(count);
|
||||
this.Value = BitConverter.ToUInt64(value, startIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
159
WelsonJS.Toolkit/EsentInterop/Update.cs
Normal file
159
WelsonJS.Toolkit/EsentInterop/Update.cs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Update.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
/// <summary>
|
||||
/// A class that encapsulates an update on a JET_TABLEID.
|
||||
/// </summary>
|
||||
public class Update : EsentResource
|
||||
{
|
||||
/// <summary>
|
||||
/// The underlying JET_SESID.
|
||||
/// </summary>
|
||||
private readonly JET_SESID sesid;
|
||||
|
||||
/// <summary>
|
||||
/// The underlying JET_TABLEID.
|
||||
/// </summary>
|
||||
private readonly JET_TABLEID tableid;
|
||||
|
||||
/// <summary>
|
||||
/// The type of update.
|
||||
/// </summary>
|
||||
private readonly JET_prep prep;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Update class. This automatically
|
||||
/// begins an update. The update will be cancelled if
|
||||
/// not explicitly saved.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to start the transaction for.</param>
|
||||
/// <param name="tableid">The tableid to prepare the update for.</param>
|
||||
/// <param name="prep">The type of update.</param>
|
||||
public Update(JET_SESID sesid, JET_TABLEID tableid, JET_prep prep)
|
||||
{
|
||||
if (JET_prep.Cancel == prep)
|
||||
{
|
||||
throw new ArgumentException("Cannot create an Update for JET_prep.Cancel", "prep");
|
||||
}
|
||||
|
||||
this.sesid = sesid;
|
||||
this.tableid = tableid;
|
||||
this.prep = prep;
|
||||
Api.JetPrepareUpdate(this.sesid, this.tableid, this.prep);
|
||||
this.ResourceWasAllocated();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="Update"/>.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.String"/> that represents the current <see cref="Update"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "Update ({0})", this.prep);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the tableid.
|
||||
/// </summary>
|
||||
/// <param name="bookmark">Returns the bookmark of the updated record. This can be null.</param>
|
||||
/// <param name="bookmarkSize">The size of the bookmark buffer.</param>
|
||||
/// <param name="actualBookmarkSize">Returns the actual size of the bookmark.</param>
|
||||
/// <remarks>
|
||||
/// Save is the final step in performing an insert or an update. The update is begun by
|
||||
/// calling creating an Update object and then by calling JetSetColumn or JetSetColumns one or more times
|
||||
/// to set the record state. Finally, Update is called to complete the update operation.
|
||||
/// Indexes are updated only by Update or and not during JetSetColumn or JetSetColumns.
|
||||
/// </remarks>
|
||||
public void Save(byte[] bookmark, int bookmarkSize, out int actualBookmarkSize)
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
if (!this.HasResource)
|
||||
{
|
||||
throw new InvalidOperationException("Not in an update");
|
||||
}
|
||||
|
||||
Api.JetUpdate(this.sesid, this.tableid, bookmark, bookmarkSize, out actualBookmarkSize);
|
||||
this.ResourceWasReleased();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the tableid.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Save is the final step in performing an insert or an update. The update is begun by
|
||||
/// calling creating an Update object and then by calling JetSetColumn or JetSetColumns one or more times
|
||||
/// to set the record state. Finally, Update is called to complete the update operation.
|
||||
/// Indexes are updated only by Update or and not during JetSetColumn or JetSetColumns.
|
||||
/// </remarks>
|
||||
public void Save()
|
||||
{
|
||||
int ignored;
|
||||
this.Save(null, 0, out ignored);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the tableid and position the tableid on the record that was modified.
|
||||
/// This can be useful when inserting a record because by default the tableid
|
||||
/// remains in its old location.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Save is the final step in performing an insert or an update. The update is begun by
|
||||
/// calling creating an Update object and then by calling JetSetColumn or JetSetColumns one or more times
|
||||
/// to set the record state. Finally, Update is called to complete the update operation.
|
||||
/// Indexes are updated only by Update or and not during JetSetColumn or JetSetColumns.
|
||||
/// </remarks>
|
||||
public void SaveAndGotoBookmark()
|
||||
{
|
||||
byte[] bookmark = null;
|
||||
|
||||
try
|
||||
{
|
||||
bookmark = Caches.BookmarkCache.Allocate();
|
||||
int actualBookmarkSize;
|
||||
this.Save(bookmark, bookmark.Length, out actualBookmarkSize);
|
||||
Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, actualBookmarkSize);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (bookmark != null)
|
||||
{
|
||||
Caches.BookmarkCache.Free(ref bookmark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancel the update.
|
||||
/// </summary>
|
||||
public void Cancel()
|
||||
{
|
||||
this.CheckObjectIsNotDisposed();
|
||||
if (!this.HasResource)
|
||||
{
|
||||
throw new InvalidOperationException("Not in an update");
|
||||
}
|
||||
|
||||
Api.JetPrepareUpdate(this.sesid, this.tableid, JET_prep.Cancel);
|
||||
this.ResourceWasReleased();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the transaction is being disposed while active.
|
||||
/// This should rollback the transaction.
|
||||
/// </summary>
|
||||
protected override void ReleaseResource()
|
||||
{
|
||||
this.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
279
WelsonJS.Toolkit/EsentInterop/Util.cs
Normal file
279
WelsonJS.Toolkit/EsentInterop/Util.cs
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="Util.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Static utility methods.
|
||||
/// </summary>
|
||||
internal static class Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Compare two byte arrays to see if they have the same content.
|
||||
/// </summary>
|
||||
/// <param name="a">The first array.</param>
|
||||
/// <param name="b">The second array.</param>
|
||||
/// <param name="offset">The offset to start comparing at.</param>
|
||||
/// <param name="count">The number of bytes to compare.</param>
|
||||
/// <returns>True if the arrays are equal, false otherwise.</returns>
|
||||
public static bool ArrayEqual(IList<byte> a, IList<byte> b, int offset, int count)
|
||||
{
|
||||
if (null == a || null == b)
|
||||
{
|
||||
return ReferenceEquals(a, b);
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
if (a[offset + i] != b[offset + i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a string containing (some of) the bytes.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to dump.</param>
|
||||
/// <param name="offset">The starting offset.</param>
|
||||
/// <param name="count">The count.</param>
|
||||
/// <returns>A string version of the data.</returns>
|
||||
public static string DumpBytes(byte[] data, int offset, int count)
|
||||
{
|
||||
if (null == data)
|
||||
{
|
||||
return "<null>";
|
||||
}
|
||||
|
||||
if (0 == count)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (offset < 0 || count < 0 || offset >= data.Length || offset + count > data.Length)
|
||||
{
|
||||
return "<invalid>";
|
||||
}
|
||||
|
||||
const int MaxBytesToPrint = 8;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append(BitConverter.ToString(data, offset, Math.Min(count, MaxBytesToPrint)));
|
||||
if (count > MaxBytesToPrint)
|
||||
{
|
||||
// The output was truncated
|
||||
sb.AppendFormat(CultureInfo.InvariantCulture, "... ({0} bytes)", count);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares two objects with ContentEquals.
|
||||
/// If both are null, there are considered equal.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">A type that implements IContentEquatable.</typeparam>
|
||||
/// <param name="left">First object to compare.</param>
|
||||
/// <param name="right">Second object to compare.</param>
|
||||
/// <returns>Whether the two objects are equal.</returns>
|
||||
public static bool ObjectContentEquals<T>(T left, T right)
|
||||
where T : class, IContentEquatable<T>
|
||||
{
|
||||
if (null == left || null == right)
|
||||
{
|
||||
return ReferenceEquals(left, right);
|
||||
}
|
||||
|
||||
return left.ContentEquals(right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares two objects with ContentEquals.
|
||||
/// If both are null, there are considered equal.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">A type that implements IContentEquatable.</typeparam>
|
||||
/// <param name="left">First object to compare.</param>
|
||||
/// <param name="right">Second object to compare.</param>
|
||||
/// <param name="length">The number of entries to compare.</param>
|
||||
/// <returns>Whether the two objects are equal.</returns>
|
||||
public static bool ArrayObjectContentEquals<T>(T[] left, T[] right, int length)
|
||||
where T : class, IContentEquatable<T>
|
||||
{
|
||||
if (null == left || null == right)
|
||||
{
|
||||
return ReferenceEquals(left, right);
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
if (!ObjectContentEquals(left[i], right[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// All the individual members are equal, all of the elements of the arrays are
|
||||
// equal, so they must be equal!
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares items in two arrays using Equals.
|
||||
/// If both arrays are null, there are considered equal.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">A value type.</typeparam>
|
||||
/// <param name="left">First array to compare.</param>
|
||||
/// <param name="right">Second array to compare.</param>
|
||||
/// <param name="length">The number of entries to compare.</param>
|
||||
/// <returns>Whether the two arrays are equal.</returns>
|
||||
public static bool ArrayStructEquals<T>(T[] left, T[] right, int length)
|
||||
where T : struct
|
||||
{
|
||||
if (null == left || null == right)
|
||||
{
|
||||
return ReferenceEquals(left, right);
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
if (!left[i].Equals(right[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// All the individual members are equal, all of the elements of the arrays are
|
||||
// equal, so they must be equal!
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clone an array of objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object in the array.</typeparam>
|
||||
/// <param name="value">The values to clone.</param>
|
||||
/// <returns>A clone of the values.</returns>
|
||||
public static T[] DeepCloneArray<T>(T[] value) where T : class, IDeepCloneable<T>
|
||||
{
|
||||
T[] clone = null;
|
||||
if (null != value)
|
||||
{
|
||||
clone = new T[value.Length];
|
||||
for (int i = 0; i < clone.Length; ++i)
|
||||
{
|
||||
clone[i] = (null == value[i]) ? null : value[i].DeepClone();
|
||||
}
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a list of hash codes calculate a hash of the hashes.
|
||||
/// </summary>
|
||||
/// <param name="hashes">The sub hash codes.</param>
|
||||
/// <returns>A hash of the hash codes.</returns>
|
||||
public static int CalculateHashCode(IEnumerable<int> hashes)
|
||||
{
|
||||
int hash = 0;
|
||||
foreach (int h in hashes)
|
||||
{
|
||||
hash ^= h;
|
||||
unchecked
|
||||
{
|
||||
hash *= 33;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a trailing directory separator character to the string.
|
||||
/// </summary>
|
||||
/// <param name="dir">The directory.</param>
|
||||
/// <returns>The directory with a separator character added (if necessary).</returns>
|
||||
public static string AddTrailingDirectorySeparator(string dir)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(dir))
|
||||
{
|
||||
var sepChars = new[] { LibraryHelpers.DirectorySeparatorChar, LibraryHelpers.AltDirectorySeparatorChar };
|
||||
return string.Concat(dir.TrimEnd(sepChars), LibraryHelpers.DirectorySeparatorChar);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a unicode string to a null-terminated Ascii byte array.
|
||||
/// </summary>
|
||||
/// <param name="value">The unicode string to be converted.</param>
|
||||
/// <returns>The byte array with a null-terminated Ascii representation of the given string.</returns>
|
||||
public static byte[] ConvertToNullTerminatedAsciiByteArray(string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] output = new byte[value.Length + 1];
|
||||
|
||||
LibraryHelpers.EncodingASCII.GetBytes(value, 0, value.Length, output, 0);
|
||||
output[output.Length - 1] = (byte)0;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a unicode string to a null-terminated Unicode byte array.
|
||||
/// </summary>
|
||||
/// <param name="value">The unicode string to be converted.</param>
|
||||
/// <returns>The byte array with a null-terminated Unicode representation of the given string.</returns>
|
||||
public static byte[] ConvertToNullTerminatedUnicodeByteArray(string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int byteArrayLength = Encoding.Unicode.GetByteCount(value);
|
||||
|
||||
byte[] output = new byte[byteArrayLength + 2];
|
||||
|
||||
Encoding.Unicode.GetBytes(value, 0, value.Length, output, 0);
|
||||
output[output.Length - 2] = (byte)0;
|
||||
output[output.Length - 1] = (byte)0;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a unicode string to an Ascii byte array.
|
||||
/// CAUTION: The array doesn't have a null-terminator at the end.
|
||||
/// </summary>
|
||||
/// <param name="value">The unicode string to be converted.</param>
|
||||
/// <returns>The byte array with an Ascii representation of the given string.</returns>
|
||||
public static byte[] ConvertToAsciiByteArray(string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] output = new byte[value.Length];
|
||||
LibraryHelpers.EncodingASCII.GetBytes(value, 0, value.Length, output, 0);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
211
WelsonJS.Toolkit/EsentInterop/VistaApi.cs
Normal file
211
WelsonJS.Toolkit/EsentInterop/VistaApi.cs
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="VistaApi.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Vista
|
||||
{
|
||||
/// <summary>
|
||||
/// ESENT APIs that were first supported in Windows Vista.
|
||||
/// </summary>
|
||||
public static class VistaApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves information about a column in a table.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="dbid">The database that contains the table.</param>
|
||||
/// <param name="tablename">The name of the table containing the column.</param>
|
||||
/// <param name="columnid">The ID of the column.</param>
|
||||
/// <param name="columnbase">Filled in with information about the columns in the table.</param>
|
||||
public static void JetGetColumnInfo(
|
||||
JET_SESID sesid,
|
||||
JET_DBID dbid,
|
||||
string tablename,
|
||||
JET_COLUMNID columnid,
|
||||
out JET_COLUMNBASE columnbase)
|
||||
{
|
||||
Api.Check(Api.Impl.JetGetColumnInfo(sesid, dbid, tablename, columnid, out columnbase));
|
||||
}
|
||||
|
||||
#region JetGetTableColumnInfo overloads
|
||||
/// <summary>
|
||||
/// Retrieves information about a table column.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">The table containing the column.</param>
|
||||
/// <param name="columnid">The columnid of the column.</param>
|
||||
/// <param name="columnbase">Filled in with information about the column.</param>
|
||||
public static void JetGetTableColumnInfo(
|
||||
JET_SESID sesid,
|
||||
JET_TABLEID tableid,
|
||||
JET_COLUMNID columnid,
|
||||
out JET_COLUMNBASE columnbase)
|
||||
{
|
||||
Api.Check(Api.Impl.JetGetTableColumnInfo(sesid, tableid, columnid, out columnbase));
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Creates a temporary table with a single index. A temporary table
|
||||
/// stores and retrieves records just like an ordinary table created
|
||||
/// using JetCreateTableColumnIndex. However, temporary tables are
|
||||
/// much faster than ordinary tables due to their volatile nature.
|
||||
/// They can also be used to very quickly sort and perform duplicate
|
||||
/// removal on record sets when accessed in a purely sequential manner.
|
||||
/// Also see
|
||||
/// <seealso cref="Api.JetOpenTempTable"/>,
|
||||
/// <seealso cref="Api.JetOpenTempTable3"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Introduced in Windows Vista. Use <see cref="Api.JetOpenTempTable3"/>
|
||||
/// for earlier versions of Esent.
|
||||
/// </remarks>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="temporarytable">
|
||||
/// Description of the temporary table to create on input. After a
|
||||
/// successful call, the structure contains the handle to the temporary
|
||||
/// table and column identifications. Use <see cref="Api.JetCloseTable"/>
|
||||
/// to free the temporary table when finished.
|
||||
/// </param>
|
||||
public static void JetOpenTemporaryTable(JET_SESID sesid, JET_OPENTEMPORARYTABLE temporarytable)
|
||||
{
|
||||
Api.Check(Api.Impl.JetOpenTemporaryTable(sesid, temporarytable));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves performance information from the database engine for the
|
||||
/// current thread. Multiple calls can be used to collect statistics
|
||||
/// that reflect the activity of the database engine on this thread
|
||||
/// between those calls.
|
||||
/// </summary>
|
||||
/// <param name="threadstats">Returns the thread statistics data.</param>
|
||||
public static void JetGetThreadStats(out JET_THREADSTATS threadstats)
|
||||
{
|
||||
Api.Check(Api.Impl.JetGetThreadStats(out threadstats));
|
||||
}
|
||||
|
||||
#if !MANAGEDESENT_ON_WSA
|
||||
/// <summary>
|
||||
/// Selects a specific instance to be part of the snapshot session.
|
||||
/// </summary>
|
||||
/// <param name="snapshot">The snapshot identifier.</param>
|
||||
/// <param name="instance">The instance to add to the snapshot.</param>
|
||||
/// <param name="grbit">Options for this call.</param>
|
||||
public static void JetOSSnapshotPrepareInstance(JET_OSSNAPID snapshot, JET_INSTANCE instance, SnapshotPrepareInstanceGrbit grbit)
|
||||
{
|
||||
Api.Check(Api.Impl.JetOSSnapshotPrepareInstance(snapshot, instance, grbit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables log truncation for all instances that are part of the snapshot session.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This function should be called only if the snapshot was created with the
|
||||
/// <see cref="VistaGrbits.ContinueAfterThaw"/> option. Otherwise, the snapshot
|
||||
/// session ends after the call to <see cref="Api.JetOSSnapshotThaw"/>.
|
||||
/// </remarks>
|
||||
/// <param name="snapshot">The snapshot identifier.</param>
|
||||
/// <param name="grbit">Options for this call.</param>
|
||||
public static void JetOSSnapshotTruncateLog(JET_OSSNAPID snapshot, SnapshotTruncateLogGrbit grbit)
|
||||
{
|
||||
Api.Check(Api.Impl.JetOSSnapshotTruncateLog(snapshot, grbit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Truncates the log for a specified instance during a snapshot session.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This function should be called only if the snapshot was created with the
|
||||
/// <see cref="VistaGrbits.ContinueAfterThaw"/> option. Otherwise, the snapshot
|
||||
/// session ends after the call to <see cref="Api.JetOSSnapshotThaw"/>.
|
||||
/// </remarks>
|
||||
/// <param name="snapshot">The snapshot identifier.</param>
|
||||
/// <param name="instance">The instance to truncat the log for.</param>
|
||||
/// <param name="grbit">Options for this call.</param>
|
||||
public static void JetOSSnapshotTruncateLogInstance(JET_OSSNAPID snapshot, JET_INSTANCE instance, SnapshotTruncateLogGrbit grbit)
|
||||
{
|
||||
Api.Check(Api.Impl.JetOSSnapshotTruncateLogInstance(snapshot, instance, grbit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of instances and databases that are part of the
|
||||
/// snapshot session at any given moment.
|
||||
/// </summary>
|
||||
/// <param name="snapshot">The identifier of the snapshot session.</param>
|
||||
/// <param name="numInstances">Returns the number of instances.</param>
|
||||
/// <param name="instances">Returns information about the instances.</param>
|
||||
/// <param name="grbit">Options for this call.</param>
|
||||
public static void JetOSSnapshotGetFreezeInfo(
|
||||
JET_OSSNAPID snapshot,
|
||||
out int numInstances,
|
||||
out JET_INSTANCE_INFO[] instances,
|
||||
SnapshotGetFreezeInfoGrbit grbit)
|
||||
{
|
||||
Api.Check(Api.Impl.JetOSSnapshotGetFreezeInfo(snapshot, out numInstances, out instances, grbit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the engine that the snapshot session finished.
|
||||
/// </summary>
|
||||
/// <param name="snapshot">The identifier of the snapshot session.</param>
|
||||
/// <param name="grbit">Snapshot end options.</param>
|
||||
public static void JetOSSnapshotEnd(JET_OSSNAPID snapshot, SnapshotEndGrbit grbit)
|
||||
{
|
||||
Api.Check(Api.Impl.JetOSSnapshotEnd(snapshot, grbit));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves information about an instance.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance to get information about.</param>
|
||||
/// <param name="signature">Retrieved information.</param>
|
||||
/// <param name="infoLevel">The type of information to retrieve.</param>
|
||||
public static void JetGetInstanceMiscInfo(JET_INSTANCE instance, out JET_SIGNATURE signature, JET_InstanceMiscInfo infoLevel)
|
||||
{
|
||||
Api.Check(Api.Impl.JetGetInstanceMiscInfo(instance, out signature, infoLevel));
|
||||
}
|
||||
#endif // !MANAGEDESENT_ON_WSA
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the ESENT database engine.
|
||||
/// </summary>
|
||||
/// <param name="instance">
|
||||
/// The instance to initialize. If an instance hasn't been
|
||||
/// allocated then a new one is created and the engine
|
||||
/// will operate in single-instance mode.
|
||||
/// </param>
|
||||
/// <param name="recoveryOptions">
|
||||
/// Additional recovery parameters for remapping databases during
|
||||
/// recovery, position where to stop recovery at, or recovery status.
|
||||
/// </param>
|
||||
/// <param name="grbit">
|
||||
/// Initialization options.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A warning code.
|
||||
/// </returns>
|
||||
public static JET_wrn JetInit3(ref JET_INSTANCE instance, JET_RSTINFO recoveryOptions, InitGrbit grbit)
|
||||
{
|
||||
return Api.Check(Api.Impl.JetInit3(ref instance, recoveryOptions, grbit));
|
||||
}
|
||||
|
||||
#if !MANAGEDESENT_ON_WSA // Not exposed in MSDK
|
||||
/// <summary>
|
||||
/// Retrieves record size information from the desired location.
|
||||
/// </summary>
|
||||
/// <param name="sesid">The session to use.</param>
|
||||
/// <param name="tableid">
|
||||
/// The cursor that will be used for the API call. The cursor must be
|
||||
/// positioned on a record, or have an update prepared.
|
||||
/// </param>
|
||||
/// <param name="recsize">Returns the size of the record.</param>
|
||||
/// <param name="grbit">Call options.</param>
|
||||
public static void JetGetRecordSize(JET_SESID sesid, JET_TABLEID tableid, ref JET_RECSIZE recsize, GetRecordSizeGrbit grbit)
|
||||
{
|
||||
Api.Check(Api.Impl.JetGetRecordSize(sesid, tableid, ref recsize, grbit));
|
||||
}
|
||||
#endif // !MANAGEDESENT_ON_WSA
|
||||
}
|
||||
}
|
||||
34
WelsonJS.Toolkit/EsentInterop/VistaColinfo.cs
Normal file
34
WelsonJS.Toolkit/EsentInterop/VistaColinfo.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
//-----------------------------------------------------------------------
|
||||
// <copyright file="VistaColinfo.cs" company="Microsoft Corporation">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.Isam.Esent.Interop.Vista
|
||||
{
|
||||
/// <summary>
|
||||
/// Column info levels that have been added to the Vista version of ESENT.
|
||||
/// </summary>
|
||||
public static class VistaColInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve the JET_COLBASE using the column id.
|
||||
/// </summary>
|
||||
internal const JET_ColInfo BaseByColid = (JET_ColInfo)8;
|
||||
|
||||
/// <summary>
|
||||
/// For lists, only return non-derived columns (if the table is derived from a template).
|
||||
/// </summary>
|
||||
internal const JET_ColInfo GrbitNonDerivedColumnsOnly = (JET_ColInfo)int.MinValue; // 0x80000000,
|
||||
|
||||
/// <summary>
|
||||
/// For lists, only return the column name and columnid of each column.
|
||||
/// </summary>
|
||||
internal const JET_ColInfo GrbitMinimalInfo = (JET_ColInfo)0x40000000;
|
||||
|
||||
/// <summary>
|
||||
/// For lists, sort returned column list by columnid (default is to sort list by column name).
|
||||
/// </summary>
|
||||
internal const JET_ColInfo GrbitSortByColumnid = (JET_ColInfo)0x20000000;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user