/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) { long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className); try { SNIAsyncCallback cb = callback ?? _sendCallback; packet.WriteToStreamAsync(_stream, cb, SNIProviders.TCP_PROV); SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "Connection Id {0}, Data sent to stream asynchronously", args0: _connectionId); return(TdsEnums.SNI_SUCCESS_IO_PENDING); } finally { SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID); } }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) { Debug.Assert(_connection != null && Monitor.IsEntered(_connection.DemuxerSync), "SNIMarsHandle.HandleRecieveComplete should be called while holding the SNIMarsConnection.DemuxerSync because it can cause deadlocks"); using (TrySNIEventScope.Create(nameof(SNIMarsHandle))) { lock (this) { _sendPacketQueue.Enqueue(new SNIMarsQueuedPacket(packet, callback ?? _handleSendCompleteCallback)); } SendPendingPackets(); SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsHandle), EventType.INFO, "MARS Session Id {0}, _sendPacketQueue enqueued, count {1}", args0: ConnectionId, args1: _sendPacketQueue?.Count); return(TdsEnums.SNI_SUCCESS_IO_PENDING); } }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public uint SendAsync(SNIPacket packet, SNIAsyncCallback callback) { long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className); try { lock (this) { return(_lowerHandle.SendAsync(packet, callback)); } } finally { SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID); } }
/// <summary> /// Send packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> private uint InternalSendAsync(SNIPacket packet, SNIAsyncCallback callback) { Debug.Assert(packet.ReservedHeaderSize == SNISMUXHeader.HEADER_LENGTH, "mars handle attempting to send muxed packet without mux reservation in InternalSendAsync"); lock (this) { if (_sequenceNumber >= _sendHighwater) { return(TdsEnums.SNI_QUEUE_FULL); } SNIPacket muxedPacket = SetPacketSMUXHeader(packet); muxedPacket.SetCompletionCallback(callback ?? HandleSendComplete); return(_connection.SendAsync(muxedPacket, callback)); } }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public uint SendAsync(SNIPacket packet, SNIAsyncCallback callback) { long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent("<sc.SNI.SNIMarsConnection.SendAsync |SNI|INFO|SCOPE> SendAsync"); try { lock (this) { return(_lowerHandle.SendAsync(packet, callback)); } } finally { SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID); } }
/// <summary> /// Write data to a stream asynchronously /// </summary> /// <param name="stream">Stream to write to</param> /// <param name="callback"></param> /// <param name="provider"></param> /// <param name="disposeAfterWriteAsync"></param> public void WriteToStreamAsync(Stream stream, SNIAsyncCallback callback, SNIProviders provider, bool disposeAfterWriteAsync = false) { // Treat local function as a static and pass all params otherwise as async will allocate async Task WriteToStreamAsync(SNIPacket packet, SNIAsyncCallback cb, SNIProviders providers, bool disposeAfter, ValueTask valueTask) { uint status = TdsEnums.SNI_SUCCESS; try { await valueTask.ConfigureAwait(false); } catch (Exception e) { SNILoadHandle.SingletonInstance.LastError = new SNIError(providers, SNICommon.InternalExceptionError, e); status = TdsEnums.SNI_ERROR; } cb(packet, status); if (disposeAfter) { packet.Dispose(); } } ValueTask vt = stream.WriteAsync(new Memory <byte>(_data, 0, _length), CancellationToken.None); if (vt.IsCompletedSuccessfully) { // Read the result to register as complete for the ValueTask vt.GetAwaiter().GetResult(); callback(this, TdsEnums.SNI_SUCCESS); if (disposeAfterWriteAsync) { Dispose(); } // Completed return; } // Not complete or error call the async local function to complete _ = WriteToStreamAsync(this, callback, provider, disposeAfterWriteAsync, vt); }
private static void SendAsyncContinuation(Task task, object rawState) { var state = (Tuple <SNITransportHandle, SNIPacket, SNIAsyncCallback>)rawState; SNITransportHandle handle = state.Item1; SNIPacket packet = state.Item2; SNIAsyncCallback callback = state.Item3; if (task.IsFaulted) { SNIError sniError = new SNIError(handle.ProviderNumber, 0, task.Exception); callback(packet, sniError); } else { callback(packet, null); } }
/// <summary> /// Write data to a stream asynchronously /// </summary> /// <param name="stream">Stream to write to</param> public void WriteToStreamAsync(Stream stream, SNIAsyncCallback callback, SNIProviders provider, bool disposeAfterWriteAsync = false) { // Treat local function as a static and pass all params otherwise as async will allocate async Task WriteToStreamAsync(SNIPacket packet, SNIAsyncCallback cb, SNIProviders providers, bool disposeAfter, Task task) { uint status = TdsEnums.SNI_SUCCESS; try { await task.ConfigureAwait(false); } catch (Exception e) { SNILoadHandle.SingletonInstance.LastError = new SNIError(providers, SNICommon.InternalExceptionError, e); status = TdsEnums.SNI_ERROR; } cb(packet, status); if (disposeAfter) { packet.Release(); } } Task t = stream.WriteAsync(_data, _headerLength, _dataLength, CancellationToken.None); if ((t.Status & TaskStatus.RanToCompletion) != 0) { // Read the result to register as complete for the Task t.GetAwaiter().GetResult(); callback(this, TdsEnums.SNI_SUCCESS); if (disposeAfterWriteAsync) { Release(); } // Completed return; } // Not complete or error call the async local function to complete _ = WriteToStreamAsync(this, callback, provider, disposeAfterWriteAsync, t); }
/// <summary> /// Read data from a stream asynchronously /// </summary> /// <param name="stream">Stream to read from</param> /// <param name="callback">Completion callback</param> public void ReadFromStreamAsync(Stream stream, SNIAsyncCallback callback, bool isMars) { bool error = false; TaskContinuationOptions options = TaskContinuationOptions.DenyChildAttach; // MARS operations during Sync ADO.Net API calls are Sync over Async. Each API call can request // threads to execute the async reads. MARS operations do not get the threads quickly enough leading to timeout // To fix the MARS thread exhaustion issue LongRunning continuation option is a temporary solution with its own drawbacks, // and should be removed after evaluating how to fix MARS threading issues efficiently if (isMars) { options |= TaskContinuationOptions.LongRunning; } stream.ReadAsync(_data, 0, _capacity, CancellationToken.None).ContinueWith(t => { Exception e = t.Exception != null ? t.Exception.InnerException : null; if (e != null) { SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, SNICommon.InternalExceptionError, e); error = true; } else { _length = t.Result; if (_length == 0) { SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, 0, SNICommon.ConnTerminatedError, string.Empty); error = true; } } if (error) { this.Release(); } callback(this, error ? TdsEnums.SNI_ERROR : TdsEnums.SNI_SUCCESS); }, CancellationToken.None, options, TaskScheduler.Default); }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) { Task writeTask = packet.WriteToStreamAsync(_stream); writeTask.ContinueWith((t) => { SNIAsyncCallback cb = callback ?? _sendCallback; uint status = TdsEnums.SNI_SUCCESS; if (t.IsFaulted) { SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, SNICommon.InternalExceptionError, t.Exception); status = TdsEnums.SNI_ERROR; } cb(packet, status); } ); return(TdsEnums.SNI_SUCCESS_IO_PENDING); }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) { long scopeID = SqlClientEventSource.Log.SNIScopeEnterEvent("<sc.SNI.SNIMarsHandle.SendAsync |SNI|INFO|SCOPE>"); try { lock (this) { _sendPacketQueue.Enqueue(new SNIMarsQueuedPacket(packet, callback ?? _handleSendCompleteCallback)); } SendPendingPackets(); return(TdsEnums.SNI_SUCCESS_IO_PENDING); } finally { SqlClientEventSource.Log.SNIScopeLeaveEvent(scopeID); } }
/// <summary> /// Send packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> private uint InternalSendAsync(SNIPacket packet, SNIAsyncCallback callback) { 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}")) { lock (this) { if (_sequenceNumber >= _sendHighwater) { SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNIMarsHandle), EventType.INFO, "MARS Session Id {0}, _sequenceNumber {1}, _sendHighwater {2}, SNI Queue is full", args0: ConnectionId, args1: _sequenceNumber, args2: _sendHighwater); return(TdsEnums.SNI_QUEUE_FULL); } SNIPacket muxedPacket = SetPacketSMUXHeader(packet); muxedPacket.SetCompletionCallback(callback ?? HandleSendComplete); 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)); } } }
/// <summary> /// Write data to a stream asynchronously /// </summary> /// <param name="stream">Stream to write to</param> /// <param name="callback">SNI Asynchronous Callback</param> /// <param name="provider">SNI provider identifier</param> /// <param name="disposeAfterWriteAsync">Bool flag to decide whether or not to dispose after Write Async operation</param> public async void WriteToStreamAsync(Stream stream, SNIAsyncCallback callback, SNIProviders provider, bool disposeAfterWriteAsync = false) { uint status = TdsEnums.SNI_SUCCESS; try { await stream.WriteAsync(_data, 0, _dataLength, CancellationToken.None).ConfigureAwait(false); } catch (Exception e) { SNILoadHandle.SingletonInstance.LastError = new SNIError(provider, SNICommon.InternalExceptionError, e); status = TdsEnums.SNI_ERROR; } callback(this, status); if (disposeAfterWriteAsync) { Dispose(); } }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) { SNIPacket newPacket = packet; _writeTaskFactory.StartNew(() => { try { lock (this) { packet.WriteToStream(_stream); } } catch (Exception e) { SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, 0, 0, e.Message); if (callback != null) { callback(packet, TdsEnums.SNI_ERROR); } else { _sendCallback(packet, TdsEnums.SNI_ERROR); } return; } if (callback != null) { callback(packet, TdsEnums.SNI_SUCCESS); } else { _sendCallback(packet, TdsEnums.SNI_SUCCESS); } }); return(TdsEnums.SNI_SUCCESS_IO_PENDING); }
public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) { SNIPacket newPacket = packet; _writeTaskFactory.StartNew(() => { try { lock (this) { packet.WriteToStream(_stream); } } catch (Exception e) { SNICommon.ReportSNIError(SNIProviders.NP_PROV, SNICommon.InternalExceptionError, e); if (callback != null) { callback(packet, TdsEnums.SNI_ERROR); } else { _sendCallback(packet, TdsEnums.SNI_ERROR); } return; } if (callback != null) { callback(packet, TdsEnums.SNI_SUCCESS); } else { _sendCallback(packet, TdsEnums.SNI_SUCCESS); } }); return(TdsEnums.SNI_SUCCESS_IO_PENDING); }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) { long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className); try { lock (this) { _sendPacketQueue.Enqueue(new SNIMarsQueuedPacket(packet, callback ?? _handleSendCompleteCallback)); } SendPendingPackets(); SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "MARS Session Id {0}, _sendPacketQueue enqueued, count {1}", args0: ConnectionId, args1: _sendPacketQueue?.Count); return(TdsEnums.SNI_SUCCESS_IO_PENDING); } finally { SqlClientEventSource.Log.TrySNIScopeLeaveEvent(scopeID); } }
/// <summary> /// Send packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> private uint InternalSendAsync(SNIPacket packet, SNIAsyncCallback callback) { lock (this) { if (_sequenceNumber >= _sendHighwater) { return(TdsEnums.SNI_QUEUE_FULL); } SNIPacket encapsulatedPacket = GetSMUXEncapsulatedPacket(packet); if (callback != null) { encapsulatedPacket.SetCompletionCallback(callback); } else { encapsulatedPacket.SetCompletionCallback(HandleSendComplete); } return(_connection.SendAsync(encapsulatedPacket, callback)); } }
/// <summary> /// Set async callbacks /// </summary> /// <param name="receiveCallback">Receive callback</param> /// <param name="sendCallback">Send callback</param> /// <summary> public override void SetAsyncCallbacks(SNIAsyncCallback receiveCallback, SNIAsyncCallback sendCallback) { _receiveCallback = receiveCallback; _sendCallback = sendCallback; }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) { SNIPacket newPacket = packet; _writeTaskFactory.StartNew(() => { try { lock (this) { packet.WriteToStream(_stream); } } catch (Exception e) { SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, SNICommon.InternalExceptionError, e); if (callback != null) { callback(packet, TdsEnums.SNI_ERROR); } else { _sendCallback(packet, TdsEnums.SNI_ERROR); } return; } if (callback != null) { callback(packet, TdsEnums.SNI_SUCCESS); } else { _sendCallback(packet, TdsEnums.SNI_SUCCESS); } }); return TdsEnums.SNI_SUCCESS_IO_PENDING; }
/// <summary> /// Set async callbacks /// </summary> /// <param name="receiveCallback">Receive callback</param> /// <param name="sendCallback">Send callback</param> public abstract void SetAsyncCallbacks(SNIAsyncCallback receiveCallback, SNIAsyncCallback sendCallback);
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public abstract uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null);
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public override uint SendAsync(SNIPacket packet, bool disposePacketAfterSendAsync, SNIAsyncCallback callback = null) { lock (this) { _sendPacketQueue.Enqueue(new SNIMarsQueuedPacket(packet, callback != null ? callback : HandleSendComplete)); } SendPendingPackets(); return(TdsEnums.SNI_SUCCESS_IO_PENDING); }
/// <summary> /// Constructor /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> public SNIMarsQueuedPacket(SNIPacket packet, SNIAsyncCallback callback) { _packet = packet; _callback = callback; }
/// <summary> /// Set async completion callback /// </summary> /// <param name="completionCallback">Completion callback</param> public void SetCompletionCallback(SNIAsyncCallback completionCallback) { _completionCallback = completionCallback; }
public override void SetAsyncCallbacks(SNIAsyncCallback receiveCallback, SNIAsyncCallback sendCallback) { _receiveCallback = receiveCallback; _sendCallback = sendCallback; }
/// <summary> /// Read data from a stream asynchronously /// </summary> /// <param name="stream">Stream to read from</param> /// <param name="callback">Completion callback</param> public void ReadFromStreamAsync(Stream stream, SNIAsyncCallback callback) {
/// <summary> /// Set async callbacks /// </summary> /// <param name="receiveCallback">Receive callback</param> /// <param name="sendCallback">Send callback</param> public override void SetAsyncCallbacks(SNIAsyncCallback receiveCallback, SNIAsyncCallback sendCallback) { Debug.Assert(false, "Should never be called for a SNIMarsHandle"); }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public override uint SendAsync(SNIPacket packet, SNIAsyncCallback callback = null) { lock (this) { _sendPacketQueue.Enqueue(new SNIMarsQueuedPacket(packet, callback != null ? callback : HandleSendComplete)); } SendPendingPackets(); return TdsEnums.SNI_SUCCESS_IO_PENDING; }
/// <summary> /// Send packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> private uint InternalSendAsync(SNIPacket packet, SNIAsyncCallback callback) { SNIPacket encapsulatedPacket = null; lock (this) { if (_sequenceNumber >= _sendHighwater) { return TdsEnums.SNI_QUEUE_FULL; } encapsulatedPacket = GetSMUXEncapsulatedPacket(packet); if (callback != null) { encapsulatedPacket.SetCompletionCallback(callback); } else { encapsulatedPacket.SetCompletionCallback(HandleSendComplete); } return _connection.SendAsync(encapsulatedPacket, callback); } }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>True if completed synchronously, otherwise false</returns> public abstract bool SendAsync(SNIPacket packet, SNIAsyncCallback callback, bool forceCallback, out SNIError error);
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public override uint SendAsync(SNIPacket packet, bool disposePacketAfterSendAsync, SNIAsyncCallback callback = null) { SNIAsyncCallback cb = callback ?? _sendCallback; lock (this) { packet.WriteToStreamAsync(_stream, cb, SNIProviders.TCP_PROV, disposePacketAfterSendAsync); } return(TdsEnums.SNI_SUCCESS_IO_PENDING); }
/// <summary> /// Constructor /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> public SNIMarsQueuedPacket(SNIPacket packet, SNIAsyncCallback callback) { Packet = packet; Callback = callback; }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public sealed override bool SendAsync(SNIPacket packet, SNIAsyncCallback callback, bool forceCallback, out SNIError sniError) { try { Task writeTask; using (_debugLock.Acquire(this)) { writeTask = packet.WriteToStreamAsync(_stream); } if (writeTask.IsCompleted && !forceCallback) { if (writeTask.IsFaulted) { sniError = new SNIError(ProviderNumber, 0, writeTask.Exception); } else { sniError = null; } return(true); } else { writeTask.ContinueWith(SendAsyncContinuation, Tuple.Create(this, packet, callback ?? _sendCallback), CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default); sniError = null; return(false); } } catch (ObjectDisposedException ode) { sniError = new SNIError(ProviderNumber, 0, ode); } catch (SocketException se) { sniError = new SNIError(ProviderNumber, 0, se); } catch (IOException ioe) { sniError = new SNIError(ProviderNumber, 0, ioe); } // Fallthrough: We caught an error Debug.Assert(sniError != null, "Should have either set an error or returned early"); if (forceCallback) { Task.Factory.StartNew(SendAsyncErrorContinuation, Tuple.Create(packet, callback ?? _sendCallback, sniError), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); sniError = null; return(false); } else { return(true); } }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="disposePacketAfterSendAsync"></param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public abstract uint SendAsync(SNIPacket packet, bool disposePacketAfterSendAsync, SNIAsyncCallback callback = null);
public override uint SendAsync(SNIPacket packet, bool disposePacketAfterSendAsync, SNIAsyncCallback callback = null) { long scopeID = SqlClientEventSource.Log.SNIScopeEnterEvent("<sc.SNI.SNINpHandle.SendAsync |SNI|SCOPE>"); try { SNIAsyncCallback cb = callback ?? _sendCallback; packet.WriteToStreamAsync(_stream, cb, SNIProviders.NP_PROV, disposePacketAfterSendAsync); return(TdsEnums.SNI_SUCCESS_IO_PENDING); } finally { SqlClientEventSource.Log.SNIScopeLeaveEvent(scopeID); } }
/// <summary> /// Send a packet asynchronously /// </summary> /// <param name="packet">SNI packet</param> /// <param name="callback">Completion callback</param> /// <returns>SNI error code</returns> public uint SendAsync(SNIPacket packet, SNIAsyncCallback callback) { lock (this) { return _lowerHandle.SendAsync(packet, callback); } }