diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 70fe79041e..8ca4487b3a 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -614,7 +614,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs index dbee403f41..7eec717a8a 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIHandle.cs @@ -51,9 +51,8 @@ internal abstract class SNIHandle /// Send a packet asynchronously /// /// SNI packet - /// Completion callback /// SNI error code - public abstract uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null); + public abstract uint SendAsync(SNIPacket packet); /// /// Receive a packet synchronously diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsConnection.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsConnection.cs index 395cfed4be..90bf83dacc 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsConnection.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsConnection.cs @@ -112,16 +112,15 @@ public uint Send(SNIPacket packet) /// Send a packet asynchronously /// /// SNI packet - /// Completion callback /// SNI error code - public uint SendAsync(SNIPacket packet, SNIAsyncCallback callback) + public uint SendAsync(SNIPacket packet) { long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className); try { lock (this) { - return _lowerHandle.SendAsync(packet, callback); + return _lowerHandle.SendAsync(packet); } } finally @@ -192,7 +191,7 @@ public void HandleReceiveError(SNIPacket packet) Debug.Assert(Monitor.IsEntered(this), "HandleReceiveError was called without being locked."); foreach (SNIMarsHandle handle in _sessions.Values) { - if (packet.HasCompletionCallback) + if (packet.HasAsyncIOCompletionCallback) { handle.HandleReceiveError(packet); #if DEBUG @@ -215,7 +214,7 @@ public void HandleReceiveError(SNIPacket packet) /// SNI error code public void HandleSendComplete(SNIPacket packet, uint sniErrorCode) { - packet.InvokeCompletionCallback(sniErrorCode); + packet.InvokeAsyncIOCompletionCallback(sniErrorCode); } /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsHandle.cs index 62eff5accc..8246ce3d6f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsHandle.cs @@ -19,7 +19,7 @@ internal sealed class SNIMarsHandle : SNIHandle private readonly SNIMarsConnection _connection; private readonly uint _status = TdsEnums.SNI_UNINITIALIZED; private readonly Queue _receivedPacketQueue = new Queue(); - private readonly Queue _sendPacketQueue = new Queue(); + private readonly Queue _sendPacketQueue = new Queue(); private readonly object _callbackObject; private readonly Guid _connectionId; private readonly ushort _sessionId; @@ -191,9 +191,8 @@ public override uint Send(SNIPacket packet) /// Send packet asynchronously /// /// SNI packet - /// Completion callback /// SNI error code - private uint InternalSendAsync(SNIPacket packet, SNIAsyncCallback callback) + private uint InternalSendAsync(SNIPacket packet) { Debug.Assert(packet.ReservedHeaderSize == SNISMUXHeader.HEADER_LENGTH, "mars handle attempting to send muxed packet without smux reservation in InternalSendAsync"); using (TrySNIEventScope.Create("SNIMarsHandle.InternalSendAsync | SNI | INFO | SCOPE | Entering Scope {0}")) @@ -207,9 +206,9 @@ private uint InternalSendAsync(SNIPacket packet, SNIAsyncCallback callback) } SNIPacket muxedPacket = SetPacketSMUXHeader(packet); - muxedPacket.SetCompletionCallback(callback ?? HandleSendComplete); + muxedPacket.SetAsyncIOCompletionCallback(_handleSendCompleteCallback); SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsHandle), EventType.INFO, "MARS Session Id {0}, _sequenceNumber {1}, _sendHighwater {2}, Sending packet", args0: ConnectionId, args1: _sequenceNumber, args2: _sendHighwater); - return _connection.SendAsync(muxedPacket, callback); + return _connection.SendAsync(muxedPacket); } } } @@ -222,7 +221,7 @@ private uint SendPendingPackets() { using (TrySNIEventScope.Create(nameof(SNIMarsHandle))) { - SNIMarsQueuedPacket packet = null; + SNIPacket packet = null; while (true) { @@ -233,7 +232,7 @@ private uint SendPendingPackets() if (_sendPacketQueue.Count != 0) { packet = _sendPacketQueue.Peek(); - uint result = InternalSendAsync(packet.Packet, packet.Callback); + uint result = InternalSendAsync(packet); if (result != TdsEnums.SNI_SUCCESS && result != TdsEnums.SNI_SUCCESS_IO_PENDING) { @@ -264,15 +263,15 @@ private uint SendPendingPackets() /// Send a packet asynchronously /// /// SNI packet - /// Completion callback /// SNI error code - public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) + public override uint SendAsync(SNIPacket packet) { using (TrySNIEventScope.Create(nameof(SNIMarsHandle))) { + packet.SetAsyncIOCompletionCallback(_handleSendCompleteCallback); lock (this) { - _sendPacketQueue.Enqueue(new SNIMarsQueuedPacket(packet, callback ?? _handleSendCompleteCallback)); + _sendPacketQueue.Enqueue(packet); } SendPendingPackets(); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsQueuedPacket.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsQueuedPacket.cs deleted file mode 100644 index 0f97eb4978..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIMarsQueuedPacket.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Microsoft.Data.SqlClient.SNI -{ - /// - /// Mars queued packet - /// - internal sealed class SNIMarsQueuedPacket - { - private readonly SNIPacket _packet; - private readonly SNIAsyncCallback _callback; - - /// - /// Constructor - /// - /// SNI packet - /// Completion callback - public SNIMarsQueuedPacket(SNIPacket packet, SNIAsyncCallback callback) - { - _packet = packet; - _callback = callback; - } - - public SNIPacket Packet => _packet; - - public SNIAsyncCallback Callback => _callback; - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs index c4ba4640f6..a3ba9e0bba 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNINpHandle.cs @@ -210,10 +210,10 @@ public override uint ReceiveAsync(ref SNIPacket packet) { SNIPacket errorPacket; packet = RentPacket(headerSize: 0, dataSize: _bufferSize); - + packet.SetAsyncIOCompletionCallback(_receiveCallback); try { - packet.ReadFromStreamAsync(_stream, _receiveCallback); + packet.ReadFromStreamAsync(_stream); SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNINpHandle), EventType.INFO, "Connection Id {0}, Rented and read packet asynchronously, dataLeft {1}", args0: _connectionId, args1: packet?.DataLeft); return TdsEnums.SNI_SUCCESS_IO_PENDING; } @@ -288,13 +288,12 @@ public override uint Send(SNIPacket packet) } } - public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) + public override uint SendAsync(SNIPacket packet) { using (TrySNIEventScope.Create(nameof(SNINpHandle))) { - SNIAsyncCallback cb = callback ?? _sendCallback; SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNINpHandle), EventType.INFO, "Connection Id {0}, Packet writing to stream, dataLeft {1}", args0: _connectionId, args1: packet?.DataLeft); - packet.WriteToStreamAsync(_stream, cb, SNIProviders.NP_PROV); + packet.WriteToStreamAsync(_stream, _sendCallback, SNIProviders.NP_PROV); return TdsEnums.SNI_SUCCESS_IO_PENDING; } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs index 58ac68c7c4..d83682021b 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIPacket.cs @@ -6,7 +6,6 @@ using System; using System.Buffers; -using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; @@ -19,14 +18,14 @@ namespace Microsoft.Data.SqlClient.SNI /// internal sealed class SNIPacket { + private static readonly Action, object> s_readCallback = ReadFromStreamAsyncContinuation; private int _dataLength; // the length of the data in the data segment, advanced by Append-ing data, does not include smux header length private int _dataCapacity; // the total capacity requested, if the array is rented this may be less than the _data.Length, does not include smux header length private int _dataOffset; // the start point of the data in the data segment, advanced by Take-ing data private int _headerLength; // the amount of space at the start of the array reserved for the smux header, this is zeroed in SetHeader // _headerOffset is not needed because it is always 0 private byte[] _data; - private SNIAsyncCallback _completionCallback; - private readonly Action, object> _readCallback; + private SNIAsyncCallback _asyncIOCompletionCallback; #if DEBUG internal readonly int _id; // in debug mode every packet is assigned a unique id so that the entire lifetime can be tracked when debugging /// refcount = 0 means that a packet should only exist in the pool @@ -85,7 +84,6 @@ public SNIPacket(SNIHandle owner, int id) #endif public SNIPacket() { - _readCallback = ReadFromStreamAsyncContinuation; } /// @@ -110,25 +108,19 @@ public SNIPacket() public int ReservedHeaderSize => _headerLength; - public bool HasCompletionCallback => !(_completionCallback is null); + public bool HasAsyncIOCompletionCallback => _asyncIOCompletionCallback is not null; /// - /// Set async completion callback + /// Set async receive callback /// - /// Completion callback - public void SetCompletionCallback(SNIAsyncCallback completionCallback) - { - _completionCallback = completionCallback; - } + /// Completion callback + public void SetAsyncIOCompletionCallback(SNIAsyncCallback asyncIOCompletionCallback) => _asyncIOCompletionCallback = asyncIOCompletionCallback; /// - /// Invoke the completion callback + /// Invoke the receive callback /// /// SNI error - public void InvokeCompletionCallback(uint sniErrorCode) - { - _completionCallback(this, sniErrorCode); - } + public void InvokeAsyncIOCompletionCallback(uint sniErrorCode) => _asyncIOCompletionCallback(this, sniErrorCode); /// /// Allocate space for data @@ -253,7 +245,7 @@ public void Release() _dataLength = 0; _dataOffset = 0; _headerLength = 0; - _completionCallback = null; + _asyncIOCompletionCallback = null; IsOutOfBand = false; } @@ -273,49 +265,48 @@ public void ReadFromStream(Stream stream) /// Read data from a stream asynchronously /// /// Stream to read from - /// Completion callback - public void ReadFromStreamAsync(Stream stream, SNIAsyncCallback callback) + public void ReadFromStreamAsync(Stream stream) { stream.ReadAsync(_data, 0, _dataCapacity, CancellationToken.None) .ContinueWith( - continuationAction: _readCallback, - state: callback, + continuationAction: s_readCallback, + state: this, CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default ); } - private void ReadFromStreamAsyncContinuation(Task t, object state) + private static void ReadFromStreamAsyncContinuation(Task task, object state) { - SNIAsyncCallback callback = (SNIAsyncCallback)state; + SNIPacket packet = (SNIPacket)state; bool error = false; - Exception e = t.Exception?.InnerException; + Exception e = task.Exception?.InnerException; if (e != null) { SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, SNICommon.InternalExceptionError, e); #if DEBUG - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIPacket), EventType.ERR, "Connection Id {0}, Internal Exception occurred while reading data: {1}", args0: _owner?.ConnectionId, args1: e?.Message); + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIPacket), EventType.ERR, "Connection Id {0}, Internal Exception occurred while reading data: {1}", args0: packet._owner?.ConnectionId, args1: e?.Message); #endif error = true; } else { - _dataLength = t.Result; + packet._dataLength = task.Result; #if DEBUG - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIPacket), EventType.INFO, "Connection Id {0}, Packet Id {1} _dataLength {2} read from stream.", args0: _owner?.ConnectionId, args1: _id, args2: _dataLength); + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIPacket), EventType.INFO, "Connection Id {0}, Packet Id {1} _dataLength {2} read from stream.", args0: packet._owner?.ConnectionId, args1: packet._id, args2: packet._dataLength); #endif - if (_dataLength == 0) + if (packet._dataLength == 0) { SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, 0, SNICommon.ConnTerminatedError, Strings.SNI_ERROR_2); #if DEBUG - SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIPacket), EventType.ERR, "Connection Id {0}, No data read from stream, connection was terminated.", args0: _owner?.ConnectionId); + SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIPacket), EventType.ERR, "Connection Id {0}, No data read from stream, connection was terminated.", args0: packet._owner?.ConnectionId); #endif error = true; } } - callback(this, error ? TdsEnums.SNI_ERROR : TdsEnums.SNI_SUCCESS); + packet.InvokeAsyncIOCompletionCallback(error ? TdsEnums.SNI_ERROR : TdsEnums.SNI_SUCCESS); } /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs index ad833e14be..e4391fb0ae 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs @@ -802,14 +802,12 @@ public override void SetAsyncCallbacks(SNIAsyncCallback receiveCallback, SNIAsyn /// Send a packet asynchronously /// /// SNI packet - /// Completion callback /// SNI error code - public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) + public override uint SendAsync(SNIPacket packet) { using (TrySNIEventScope.Create(nameof(SNITCPHandle))) { - SNIAsyncCallback cb = callback ?? _sendCallback; - packet.WriteToStreamAsync(_stream, cb, SNIProviders.TCP_PROV); + packet.WriteToStreamAsync(_stream, _sendCallback, SNIProviders.TCP_PROV); SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.INFO, "Connection Id {0}, Data sent to stream asynchronously", args0: _connectionId); return TdsEnums.SNI_SUCCESS_IO_PENDING; } @@ -824,10 +822,10 @@ public override uint ReceiveAsync(ref SNIPacket packet) { SNIPacket errorPacket; packet = RentPacket(headerSize: 0, dataSize: _bufferSize); - + packet.SetAsyncIOCompletionCallback(_receiveCallback); try { - packet.ReadFromStreamAsync(_stream, _receiveCallback); + packet.ReadFromStreamAsync(_stream); SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.INFO, "Connection Id {0}, Data received from stream asynchronously", args0: _connectionId); return TdsEnums.SNI_SUCCESS_IO_PENDING; }