diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs index 5e1e268b06..bb3b07b0e8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs @@ -86,8 +86,6 @@ internal abstract void CreatePhysicalSNIHandle( internal abstract void AssignPendingDNSInfo(string userProtocol, string DNSCacheKey, ref SQLDNSInfo pendingDNSInfo); - internal abstract bool IsFailedHandle(); - protected abstract void CreateSessionHandle(TdsParserStateObject physicalConnection, bool async); protected abstract void FreeGcHandle(int remaining, bool release); @@ -98,28 +96,8 @@ internal abstract void CreatePhysicalSNIHandle( internal abstract void Dispose(); - internal abstract void DisposePacketCache(); - - internal abstract bool IsPacketEmpty(PacketHandle readPacket); - - internal abstract PacketHandle ReadSyncOverAsync(int timeoutRemaining, out uint error); - - internal abstract PacketHandle ReadAsync(SessionHandle handle, out uint error); - internal abstract uint CheckConnection(); - internal abstract void ReleasePacket(PacketHandle syncReadPacket); - - protected abstract uint SniPacketGetData(PacketHandle packet, byte[] _inBuff, ref uint dataSize); - - internal abstract PacketHandle GetResetWritePacket(int dataSize); - - internal abstract void ClearAllWritePackets(); - - internal abstract PacketHandle AddPacketToPendingList(PacketHandle packet); - - protected abstract void RemovePacketFromPendingList(PacketHandle pointer); - internal int DecrementPendingCallbacks(bool release) { int remaining = Interlocked.Decrement(ref _pendingCallbacks); @@ -412,8 +390,6 @@ public void ReadAsyncCallback(IntPtr key, PacketHandle packet, uint error) } } - protected abstract bool CheckPacket(PacketHandle packet, TaskCompletionSource source); - public void WriteAsyncCallback(PacketHandle packet, uint sniError) => WriteAsyncCallback(IntPtr.Zero, packet, sniError); @@ -719,10 +695,6 @@ private Task SNIWritePacket(PacketHandle packet, out uint sniError, bool canAccu return task; } - internal abstract bool IsValidPacket(PacketHandle packetPointer); - - internal abstract uint WritePacket(PacketHandle packet, bool sync); - // Sends an attention signal - executing thread will consume attn. internal void SendAttention(bool mustTakeWriteLock = false, bool asyncClose = false) { @@ -871,7 +843,5 @@ private void SniWriteStatisticsAndTracing() statistics.RequestNetworkServerTimer(); } } - - protected abstract PacketHandle EmptyReadPacket { get; } } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs index b8d1b6cccb..10e9d96eca 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs @@ -43,23 +43,34 @@ private enum NativeProtocols internal SNIPacket _sniAsyncAttnPacket = null; // Packet to use to send Attn private readonly WritePacketCache _writePacketCache = new WritePacketCache(); // Store write packets that are ready to be re-used - public TdsParserStateObjectNative(TdsParser parser) : base(parser) { } - private GCHandle _gcHandle; // keeps this object alive until we're closed. - private Dictionary _pendingWritePackets = new Dictionary(); // Stores write packets that have been sent to SNI, but have not yet finished writing (i.e. we are waiting for SNI's callback) + private readonly Dictionary _pendingWritePackets = new Dictionary(); // Stores write packets that have been sent to SNI, but have not yet finished writing (i.e. we are waiting for SNI's callback) - internal TdsParserStateObjectNative(TdsParser parser, TdsParserStateObject physicalConnection, bool async) : - base(parser, physicalConnection, async) + internal TdsParserStateObjectNative(TdsParser parser, TdsParserStateObject physicalConnection, bool async) + : base(parser, physicalConnection, async) { } + public TdsParserStateObjectNative(TdsParser parser) + : base(parser) + { + } + + //////////////// + // Properties // + //////////////// + internal SNIHandle Handle => _sessionHandle; internal override uint Status => _sessionHandle != null ? _sessionHandle.Status : TdsEnums.SNI_UNINITIALIZED; internal override SessionHandle SessionHandle => SessionHandle.FromNativeHandle(_sessionHandle); + protected override PacketHandle EmptyReadPacket => PacketHandle.FromNativePointer(default); + + internal override Guid? SessionId => default; + protected override void CreateSessionHandle(TdsParserStateObject physicalConnection, bool async) { Debug.Assert(physicalConnection is TdsParserStateObjectNative, "Expected a stateObject of type " + this.GetType()); @@ -256,22 +267,6 @@ protected override void FreeGcHandle(int remaining, bool release) internal override bool IsFailedHandle() => _sessionHandle.Status != TdsEnums.SNI_SUCCESS; - internal override PacketHandle ReadSyncOverAsync(int timeoutRemaining, out uint error) - { - SNIHandle handle = Handle; - if (handle == null) - { - throw ADP.ClosedConnectionError(); - } - IntPtr readPacketPtr = IntPtr.Zero; - error = SniNativeWrapper.SniReadSyncOverAsync(handle, ref readPacketPtr, GetTimeoutRemaining()); - return PacketHandle.FromNativePointer(readPacketPtr); - } - - protected override PacketHandle EmptyReadPacket => PacketHandle.FromNativePointer(default); - - internal override Guid? SessionId => default; - internal override bool IsPacketEmpty(PacketHandle readPacket) { Debug.Assert(readPacket.Type == PacketHandle.NativePointerType || readPacket.Type == 0, "unexpected packet type when requiring NativePointer"); @@ -298,6 +293,14 @@ internal override PacketHandle ReadAsync(SessionHandle handle, out uint error) return PacketHandle.FromNativePointer(readPacketPtr); } + internal override PacketHandle ReadSyncOverAsync(int timeoutRemaining, out uint error) + { + SNIHandle handle = Handle ?? throw ADP.ClosedConnectionError(); + IntPtr readPacketPtr = IntPtr.Zero; + error = SniNativeWrapper.SniReadSyncOverAsync(handle, ref readPacketPtr, GetTimeoutRemaining()); + return PacketHandle.FromNativePointer(readPacketPtr); + } + internal override PacketHandle CreateAndSetAttentionPacket() { SNIHandle handle = Handle; @@ -332,11 +335,9 @@ internal override PacketHandle AddPacketToPendingList(PacketHandle packetToAdd) internal override bool IsValidPacket(PacketHandle packetPointer) { Debug.Assert(packetPointer.Type == PacketHandle.NativePointerType || packetPointer.Type == PacketHandle.NativePacketType, "unexpected packet type when requiring NativePointer"); - return ( - (packetPointer.Type == PacketHandle.NativePointerType && packetPointer.NativePointer != IntPtr.Zero) - || - (packetPointer.Type == PacketHandle.NativePacketType && packetPointer.NativePacket != null) - ); + + return (packetPointer.Type == PacketHandle.NativePointerType && packetPointer.NativePointer != IntPtr.Zero) + || (packetPointer.Type == PacketHandle.NativePacketType && packetPointer.NativePacket != null); } internal override PacketHandle GetResetWritePacket(int dataSize) @@ -444,8 +445,16 @@ internal override void DisposePacketCache() { lock (_writePacketLockObject) { - _writePacketCache.Dispose(); - // Do not set _writePacketCache to null, just in case a WriteAsyncCallback completes after this point +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif + try + { } + finally + { + _writePacketCache.Dispose(); + // Do not set _writePacketCache to null, just in case a WriteAsyncCallback completes after this point + } } } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs index d061e759c9..cf54e0340f 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs @@ -23,10 +23,8 @@ internal partial class TdsParserStateObject protected SNIHandle _sessionHandle = null; // the SNI handle we're to work on // SNI variables // multiple resultsets in one batch. - private SNIPacket _sniPacket = null; // Will have to re-vamp this for MARS + protected SNIPacket _sniPacket = null; // Will have to re-vamp this for MARS internal SNIPacket _sniAsyncAttnPacket = null; // Packet to use to send Attn - private readonly WritePacketCache _writePacketCache = new WritePacketCache(); // Store write packets that are ready to be re-used - private readonly Dictionary _pendingWritePackets = new Dictionary(); // Stores write packets that have been sent to SNI, but have not yet finished writing (i.e. we are waiting for SNI's callback) // Async variables private GCHandle _gcHandle; // keeps this object alive until we're closed. @@ -64,7 +62,7 @@ protected TdsParserStateObject(TdsParser parser, SNIHandle physicalConnection, b SQLFallbackDNSCache.Instance.GetDNSInfo(_parser.FQDNforDNSCache, out cachedDNSInfo); _sessionHandle = new SNIHandle(myInfo, physicalConnection, _parser.Connection.ConnectionOptions.IPAddressPreference, cachedDNSInfo); - if (_sessionHandle.Status != TdsEnums.SNI_SUCCESS) + if (IsFailedHandle()) { AddError(parser.ProcessSNIError(this)); ThrowExceptionAndWarning(); @@ -136,35 +134,8 @@ internal void CreatePhysicalSNIHandle( ipPreference, cachedDNSInfo, hostNameInCertificate); } - internal bool IsPacketEmpty(PacketHandle readPacket) - { - Debug.Assert(readPacket.Type == PacketHandle.NativePointerType || readPacket.Type == 0, "unexpected packet type when requiring NativePointer"); - return IntPtr.Zero == readPacket.NativePointer; - } - - internal PacketHandle ReadSyncOverAsync(int timeoutRemaining, out uint error) - { - SNIHandle handle = Handle ?? throw ADP.ClosedConnectionError(); - IntPtr readPacketPtr = IntPtr.Zero; - error = SniNativeWrapper.SniReadSyncOverAsync(handle, ref readPacketPtr, timeoutRemaining); - return PacketHandle.FromNativePointer(readPacketPtr); - } - - internal PacketHandle ReadAsync(SessionHandle handle, out uint error) - { - IntPtr readPacketPtr = IntPtr.Zero; - error = SniNativeWrapper.SniReadAsync(handle.NativeHandle, ref readPacketPtr); - return PacketHandle.FromNativePointer(readPacketPtr); - } - internal uint CheckConnection() => SniNativeWrapper.SniCheckConnection(Handle); - internal void ReleasePacket(PacketHandle syncReadPacket) - { - Debug.Assert(syncReadPacket.Type == PacketHandle.NativePointerType, "unexpected packet type when requiring NativePointer"); - SniNativeWrapper.SniPacketRelease(syncReadPacket.NativePointer); - } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal int DecrementPendingCallbacks(bool release) { @@ -224,20 +195,7 @@ internal void Dispose() } } - if (_writePacketCache != null) - { - lock (_writePacketLockObject) - { - RuntimeHelpers.PrepareConstrainedRegions(); - try - { } - finally - { - _writePacketCache.Dispose(); - // Do not set _writePacketCache to null, just in case a WriteAsyncCallback completes after this point - } - } - } + DisposePacketCache(); } /// @@ -386,12 +344,6 @@ private uint GetSniPacket(PacketHandle packet, ref uint dataSize) return SniPacketGetData(packet, _inBuff, ref dataSize); } - private uint SniPacketGetData(PacketHandle packet, byte[] _inBuff, ref uint dataSize) - { - Debug.Assert(packet.Type == PacketHandle.NativePointerType, "unexpected packet type when requiring NativePointer"); - return SniNativeWrapper.SniPacketGetData(packet.NativePointer, _inBuff, ref dataSize); - } - public void ReadAsyncCallback(IntPtr key, PacketHandle packet, uint error) { // Key never used. @@ -493,13 +445,6 @@ public void ReadAsyncCallback(IntPtr key, PacketHandle packet, uint error) } } - private bool CheckPacket(PacketHandle packet, TaskCompletionSource source) - { - Debug.Assert(packet.Type == PacketHandle.NativePointerType, "unexpected packet type when requiring NativePointer"); - IntPtr ptr = packet.NativePointer; - return IntPtr.Zero == ptr || IntPtr.Zero != ptr && source != null; - } - #pragma warning disable 420 // a reference to a volatile field will not be treated as volatile public void WriteAsyncCallback(IntPtr key, PacketHandle packet, uint sniError) @@ -715,8 +660,7 @@ private Task SNIWritePacket(PacketHandle packet, out uint sniError, bool canAccu } finally { - Debug.Assert(packet.Type == PacketHandle.NativePacketType, "unexpected packet type when requiring NativePacket"); - sniError = SniNativeWrapper.SniWritePacket(Handle, packet.NativePacket, sync); + sniError = WritePacket(packet, sync); } if (sniError == TdsEnums.SNI_SUCCESS_IO_PENDING) @@ -810,16 +754,6 @@ private Task SNIWritePacket(PacketHandle packet, out uint sniError, bool canAccu #pragma warning restore 420 - internal bool IsValidPacket(PacketHandle packetPointer) - { - Debug.Assert(packetPointer.Type == PacketHandle.NativePointerType || packetPointer.Type == PacketHandle.NativePacketType, "unexpected packet type when requiring NativePointer"); - return ( - (packetPointer.Type == PacketHandle.NativePointerType && packetPointer.NativePointer != IntPtr.Zero) - || - (packetPointer.Type == PacketHandle.NativePacketType && packetPointer.NativePacket != null) - ); - } - // Sends an attention signal - executing thread will consume attn. internal void SendAttention(bool mustTakeWriteLock = false, bool asyncClose = false) { @@ -904,7 +838,7 @@ internal PacketHandle CreateAndSetAttentionPacket() private Task WriteSni(bool canAccumulate) { // Prepare packet, and write to packet. - PacketHandle packet = GetResetWritePacket(); + PacketHandle packet = GetResetWritePacket(_outBytesUsed); SNIPacket nativePacket = packet.NativePacket; SniNativeWrapper.SniPacketSetData(nativePacket, _outBuff, _outBytesUsed, _securePasswords, _securePasswordOffsetsInBuffer); @@ -957,73 +891,6 @@ private Task WriteSni(bool canAccumulate) return task; } - internal PacketHandle GetResetWritePacket() - { - if (_sniPacket != null) - { - SniNativeWrapper.SniPacketReset(Handle, IoType.WRITE, _sniPacket, ConsumerNumber.SNI_Consumer_SNI); - } - else - { - lock (_writePacketLockObject) - { - _sniPacket = _writePacketCache.Take(Handle); - } - } - return PacketHandle.FromNativePacket(_sniPacket); - } - - internal void ClearAllWritePackets() - { - if (_sniPacket != null) - { - _sniPacket.Dispose(); - _sniPacket = null; - } - lock (_writePacketLockObject) - { - Debug.Assert(_pendingWritePackets.Count == 0 && _asyncWriteCount == 0, "Should not clear all write packets if there are packets pending"); - _writePacketCache.Clear(); - } - } - - private PacketHandle AddPacketToPendingList(PacketHandle packetToAdd) - { - Debug.Assert(packetToAdd.Type == PacketHandle.NativePacketType, "unexpected packet type when requiring NativePacket"); - SNIPacket packet = packetToAdd.NativePacket; - Debug.Assert(packet == _sniPacket, "Adding a packet other than the current packet to the pending list"); - _sniPacket = null; - IntPtr pointer = packet.DangerousGetHandle(); - - lock (_writePacketLockObject) - { - _pendingWritePackets.Add(pointer, packet); - } - - return PacketHandle.FromNativePointer(pointer); - } - - private void RemovePacketFromPendingList(PacketHandle ptr) - { - Debug.Assert(ptr.Type == PacketHandle.NativePointerType, "unexpected packet type when requiring NativePointer"); - IntPtr pointer = ptr.NativePointer; - - lock (_writePacketLockObject) - { - if (_pendingWritePackets.TryGetValue(pointer, out SNIPacket recoveredPacket)) - { - _pendingWritePackets.Remove(pointer); - _writePacketCache.Add(recoveredPacket); - } -#if DEBUG - else - { - Debug.Assert(false, "Removing a packet from the pending list that was never added to it"); - } -#endif - } - } - ////////////////////////////////////////////// // Statistics, Tracing, and related methods // ////////////////////////////////////////////// @@ -1069,7 +936,5 @@ private void SniWriteStatisticsAndTracing() } SqlClientEventSource.Log.TryAdvancedTraceBinEvent("TdsParser.WritePacket | INFO | ADV | State Object Id {0}, Packet sent. Out buffer: {1}, Out Bytes Used: {2}", ObjectID, _outBuff, _outBytesUsed); } - - protected PacketHandle EmptyReadPacket => PacketHandle.FromNativePointer(default); } } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs index ea14931af7..2ad67cf2f4 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.cs @@ -3,18 +3,27 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; using Interop.Windows.Sni; +using Microsoft.Data.Common; namespace Microsoft.Data.SqlClient { internal class TdsParserStateObjectNative : TdsParserStateObject { + private readonly WritePacketCache _writePacketCache = new WritePacketCache(); // Store write packets that are ready to be re-used + + private readonly Dictionary _pendingWritePackets = new Dictionary(); // Stores write packets that have been sent to SNI, but have not yet finished writing (i.e. we are waiting for SNI's callback) + internal TdsParserStateObjectNative(TdsParser parser, TdsParserStateObject physicalConnection, bool async) : base(parser, physicalConnection.Handle, async) { } - internal TdsParserStateObjectNative(TdsParser parser) + public TdsParserStateObjectNative(TdsParser parser) : base(parser) { } @@ -27,8 +36,133 @@ internal TdsParserStateObjectNative(TdsParser parser) internal override SessionHandle SessionHandle => SessionHandle.FromNativeHandle(_sessionHandle); + protected override PacketHandle EmptyReadPacket => PacketHandle.FromNativePointer(default); + internal override Guid? SessionId => default; + protected override uint SniPacketGetData(PacketHandle packet, byte[] _inBuff, ref uint dataSize) + { + Debug.Assert(packet.Type == PacketHandle.NativePointerType, "unexpected packet type when requiring NativePointer"); + return SniNativeWrapper.SniPacketGetData(packet.NativePointer, _inBuff, ref dataSize); + } + + protected override bool CheckPacket(PacketHandle packet, TaskCompletionSource source) + { + Debug.Assert(packet.Type == PacketHandle.NativePointerType, "unexpected packet type when requiring NativePointer"); + IntPtr ptr = packet.NativePointer; + return IntPtr.Zero == ptr || IntPtr.Zero != ptr && source != null; + } + + protected override void RemovePacketFromPendingList(PacketHandle ptr) + { + Debug.Assert(ptr.Type == PacketHandle.NativePointerType, "unexpected packet type when requiring NativePointer"); + IntPtr pointer = ptr.NativePointer; + + lock (_writePacketLockObject) + { + if (_pendingWritePackets.TryGetValue(pointer, out SNIPacket recoveredPacket)) + { + _pendingWritePackets.Remove(pointer); + _writePacketCache.Add(recoveredPacket); + } +#if DEBUG + else + { + Debug.Fail("Removing a packet from the pending list that was never added to it"); + } +#endif + } + } + + internal override bool IsFailedHandle() => _sessionHandle.Status != TdsEnums.SNI_SUCCESS; + + internal override bool IsPacketEmpty(PacketHandle readPacket) + { + Debug.Assert(readPacket.Type == PacketHandle.NativePointerType || readPacket.Type == 0, "unexpected packet type when requiring NativePointer"); + return IntPtr.Zero == readPacket.NativePointer; + } + + internal override void ReleasePacket(PacketHandle syncReadPacket) + { + Debug.Assert(syncReadPacket.Type == PacketHandle.NativePointerType, "unexpected packet type when requiring NativePointer"); + SniNativeWrapper.SniPacketRelease(syncReadPacket.NativePointer); + } + + internal override PacketHandle ReadAsync(SessionHandle handle, out uint error) + { + IntPtr readPacketPtr = IntPtr.Zero; + error = SniNativeWrapper.SniReadAsync(handle.NativeHandle, ref readPacketPtr); + return PacketHandle.FromNativePointer(readPacketPtr); + } + + internal override PacketHandle ReadSyncOverAsync(int timeoutRemaining, out uint error) + { + SNIHandle handle = Handle ?? throw ADP.ClosedConnectionError(); + IntPtr readPacketPtr = IntPtr.Zero; + error = SniNativeWrapper.SniReadSyncOverAsync(handle, ref readPacketPtr, timeoutRemaining); + return PacketHandle.FromNativePointer(readPacketPtr); + } + + internal override uint WritePacket(PacketHandle packet, bool sync) + { + Debug.Assert(packet.Type == PacketHandle.NativePacketType, "unexpected packet type when requiring NativePacket"); + return SniNativeWrapper.SniWritePacket(Handle, packet.NativePacket, sync); + } + + internal override PacketHandle AddPacketToPendingList(PacketHandle packetToAdd) + { + Debug.Assert(packetToAdd.Type == PacketHandle.NativePacketType, "unexpected packet type when requiring NativePacket"); + SNIPacket packet = packetToAdd.NativePacket; + Debug.Assert(packet == _sniPacket, "Adding a packet other than the current packet to the pending list"); + _sniPacket = null; + IntPtr pointer = packet.DangerousGetHandle(); + + lock (_writePacketLockObject) + { + _pendingWritePackets.Add(pointer, packet); + } + + return PacketHandle.FromNativePointer(pointer); + } + + internal override bool IsValidPacket(PacketHandle packetPointer) + { + Debug.Assert(packetPointer.Type == PacketHandle.NativePointerType || packetPointer.Type == PacketHandle.NativePacketType, "unexpected packet type when requiring NativePointer"); + + return (packetPointer.Type == PacketHandle.NativePointerType && packetPointer.NativePointer != IntPtr.Zero) + || (packetPointer.Type == PacketHandle.NativePacketType && packetPointer.NativePacket != null); + } + + internal override PacketHandle GetResetWritePacket(int dataSize) + { + if (_sniPacket != null) + { + SniNativeWrapper.SniPacketReset(Handle, IoType.WRITE, _sniPacket, ConsumerNumber.SNI_Consumer_SNI); + } + else + { + lock (_writePacketLockObject) + { + _sniPacket = _writePacketCache.Take(Handle); + } + } + return PacketHandle.FromNativePacket(_sniPacket); + } + + internal override void ClearAllWritePackets() + { + if (_sniPacket != null) + { + _sniPacket.Dispose(); + _sniPacket = null; + } + lock (_writePacketLockObject) + { + Debug.Assert(_pendingWritePackets.Count == 0 && _asyncWriteCount == 0, "Should not clear all write packets if there are packets pending"); + _writePacketCache.Clear(); + } + } + internal override uint SniGetConnectionId(ref Guid clientConnectionId) => SniNativeWrapper.SniGetConnectionId(Handle, ref clientConnectionId); @@ -41,6 +175,23 @@ internal override uint EnableMars(ref uint info) internal override uint SetConnectionBufferSize(ref uint unsignedPacketSize) => SniNativeWrapper.SniSetInfo(Handle, QueryType.SNI_QUERY_CONN_BUFSIZE, ref unsignedPacketSize); + internal override void DisposePacketCache() + { + lock (_writePacketLockObject) + { +#if NETFRAMEWORK + RuntimeHelpers.PrepareConstrainedRegions(); +#endif + try + { } + finally + { + _writePacketCache.Dispose(); + // Do not set _writePacketCache to null, just in case a WriteAsyncCallback completes after this point + } + } + } + internal override SspiContextProvider CreateSspiContextProvider() => new NativeSspiContextProvider(); } } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index 61cc18b536..2eef6adbe0 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -481,6 +481,34 @@ internal long TimeoutTime internal abstract SessionHandle SessionHandle { get; } + protected abstract PacketHandle EmptyReadPacket { get; } + + internal abstract PacketHandle GetResetWritePacket(int dataSize); + + protected abstract uint SniPacketGetData(PacketHandle packet, byte[] _inBuff, ref uint dataSize); + + protected abstract bool CheckPacket(PacketHandle packet, TaskCompletionSource source); + + internal abstract bool IsFailedHandle(); + + internal abstract bool IsPacketEmpty(PacketHandle readPacket); + + internal abstract void ReleasePacket(PacketHandle syncReadPacket); + + internal abstract PacketHandle ReadSyncOverAsync(int timeoutRemaining, out uint error); + + internal abstract uint WritePacket(PacketHandle packet, bool sync); + + internal abstract PacketHandle AddPacketToPendingList(PacketHandle packet); + + protected abstract void RemovePacketFromPendingList(PacketHandle pointer); + + internal abstract void ClearAllWritePackets(); + + internal abstract bool IsValidPacket(PacketHandle packetPointer); + + internal abstract PacketHandle ReadAsync(SessionHandle handle, out uint error); + internal abstract uint SniGetConnectionId(ref Guid clientConnectionId); internal abstract uint DisableSsl(); @@ -491,6 +519,8 @@ internal long TimeoutTime internal abstract uint SetConnectionBufferSize(ref uint unsignedPacketSize); + internal abstract void DisposePacketCache(); + internal int GetTimeoutRemaining() { int remaining;