public void Add(SNIPacket packet) { if (!_disposed) { _packets.Push(packet); } else { // If we're disposed, then get rid of any packets added to us packet.Dispose(); } }
internal void Dispose() { SafeHandle handle2 = this._sniPacket; SafeHandle handle = this._sessionHandle; SafeHandle handle3 = this._sniAsyncAttnPacket; this._sniPacket = null; this._sessionHandle = null; this._sniAsyncAttnPacket = null; if ((handle != null) || (handle2 != null)) { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (handle2 != null) { handle2.Dispose(); } if (handle3 != null) { handle3.Dispose(); } if (handle != null) { handle.Dispose(); this.DecrementPendingCallbacks(true); } } } }
public SNIPacket Take(SNIHandle sniHandle) { SNIPacket packet; if (_packets.Count > 0) { // Success - reset the packet packet = _packets.Pop(); SNINativeMethodWrapper.SNIPacketReset(sniHandle, SNINativeMethodWrapper.IOType.WRITE, packet, SNINativeMethodWrapper.ConsumerNumber.SNI_Consumer_SNI); } else { // Failed to take a packet - create a new one packet = new SNIPacket(sniHandle); } return packet; }
public static uint SNIWritePacket(SafeHandle handle, SNIPacket packet, bool sync) { throw new NotSupportedException(msg); }
private void WriteSni() { uint num; if (this._sniPacket == null) { this._sniPacket = new SNIPacket(this.Handle); } else { SNINativeMethodWrapper.SNIPacketReset(this.Handle, SNINativeMethodWrapper.IOType.WRITE, this._sniPacket, SNINativeMethodWrapper.ConsumerNumber.SNI_Consumer_SNI); } SNINativeMethodWrapper.SNIPacketSetData(this._sniPacket, this._outBuff, this._outBytesUsed); if (this._parser.AsyncOn) { if (this._cachedAsyncResult == null) { this._cachedAsyncResult = new DbAsyncResult(this._parser, string.Empty, null, null, null); } this._asyncResult = this._cachedAsyncResult; num = this.SNIWriteAsync(this.Handle, this._sniPacket, this._cachedAsyncResult); } else { num = SNINativeMethodWrapper.SNIWriteSync(this.Handle, this._sniPacket); if (num != 0) { Bid.Trace("<sc.TdsParser.WritePacket|Info> write sync returned error code %d\n", (int) num); this._parser.Errors.Add(this._parser.ProcessSNIError(this)); this.ThrowExceptionAndWarning(); } if (this._bulkCopyOpperationInProgress && (TdsParserStaticMethods.GetTimeoutMilliseconds(this.TimeoutTime) == 0)) { this._parser.Errors.Add(new SqlError(-2, 0, 11, this._parser.Server, SQLMessage.Timeout(), "", 0)); this.SendAttention(); this._parser.ProcessPendingAck(this); this._parser.ThrowExceptionAndWarning(); } } if ((this._parser.State == TdsParserState.OpenNotLoggedIn) && (this._parser.EncryptionOptions == EncryptionOptions.LOGIN)) { this._parser.RemoveEncryption(); this._parser.EncryptionOptions = EncryptionOptions.OFF; this._sniPacket.Dispose(); this._sniPacket = new SNIPacket(this.Handle); } this.SniWriteStatisticsAndTracing(); this.ResetBuffer(); }
internal SNIPacket GetResetWritePacket() { if (_sniPacket != null) { SNINativeMethodWrapper.SNIPacketReset(Handle, SNINativeMethodWrapper.IOType.WRITE, _sniPacket, SNINativeMethodWrapper.ConsumerNumber.SNI_Consumer_SNI); } else { lock (_writePacketLockObject) { _sniPacket = _writePacketCache.Take(Handle); } } return _sniPacket; }
private IntPtr AddPacketToPendingList(SNIPacket packet) { 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 pointer; }
private static unsafe extern void SNIPacketSetData(SNIPacket pPacket, [In] byte* pbBuf, uint cbBuf);
internal static unsafe void SNIPacketSetData(SNIPacket packet, byte[] data, int length) { fixed (byte* pin_data = &data[0]) { SNIPacketSetData(packet, pin_data, (uint)length); } }
private static extern uint SNIWriteSyncOverAsync(SNIHandle pConn, [In] SNIPacket pPacket);
internal static extern void SNIPacketReset([In] SNIHandle pConn, IOType IOType, SNIPacket pPacket, ConsumerNumber ConsNum);
private static extern uint SNIWriteAsyncWrapper(SNIHandle pConn, [In] SNIPacket pPacket);
private static extern unsafe void SNIPacketSetData(SNIPacket pPacket, [In] byte *pbBuf, uint cbBuf);
internal static extern void SNIPacketReset([In] SNIHandle pConn, IOType IOType, SNIPacket pPacket, ConsumerNumber ConsNum);
#pragma warning disable 0420 // a reference to a volatile field will not be treated as volatile private Task SNIWritePacket(SNIHandle handle, SNIPacket packet, out UInt32 sniError, bool canAccumulate, bool callerHasConnectionLock) { // Check for a stored exception var delayedException = Interlocked.Exchange(ref _delayedWriteAsyncCallbackException, null); if (delayedException != null) { throw delayedException; } Task task = null; _writeCompletionSource = null; IntPtr packetPointer = IntPtr.Zero; bool sync = !_parser._asyncWrite; if (sync && _asyncWriteCount > 0) { // for example, SendAttention while there are writes pending Task waitForWrites = WaitForAccumulatedWrites(); if (waitForWrites != null) { try { waitForWrites.Wait(); } catch (AggregateException ae) { throw ae.InnerException; } } Debug.Assert(_asyncWriteCount == 0, "All async write should be finished"); } if (!sync) { // Add packet to the pending list (since the callback can happen any time after we call SNIWritePacket) packetPointer = AddPacketToPendingList(packet); } // Async operation completion may be delayed (success pending). try { } finally { sniError = SNINativeMethodWrapper.SNIWritePacket(handle, packet, sync); } if (sniError == TdsEnums.SNI_SUCCESS_IO_PENDING) { Debug.Assert(!sync, "Completion should be handled in SniManagedWwrapper"); Interlocked.Increment(ref _asyncWriteCount); Debug.Assert(_asyncWriteCount >= 0); if (!canAccumulate) { // Create completion source (for callback to complete) _writeCompletionSource = new TaskCompletionSource<object>(); task = _writeCompletionSource.Task; // Ensure that setting _writeCompletionSource completes before checking _delayedWriteAsyncCallbackException Interlocked.MemoryBarrier(); // Check for a stored exception delayedException = Interlocked.Exchange(ref _delayedWriteAsyncCallbackException, null); if (delayedException != null) { throw delayedException; } // If there are no outstanding writes, see if we can shortcut and return null if ((_asyncWriteCount == 0) && ((!task.IsCompleted) || (task.Exception == null))) { task = null; } } } #if DEBUG else if (!sync && !canAccumulate && SqlCommand.DebugForceAsyncWriteDelay > 0) { // Executed synchronously - callback will not be called TaskCompletionSource<object> completion = new TaskCompletionSource<object>(); uint error = sniError; new Timer(obj => { try { if (_parser.MARSOn) { // Only take reset lock on MARS. CheckSetResetConnectionState(error, CallbackType.Write); } if (error != TdsEnums.SNI_SUCCESS) { AddError(_parser.ProcessSNIError(this)); ThrowExceptionAndWarning(); } AssertValidState(); completion.SetResult(null); } catch (Exception e) { completion.SetException(e); } }, null, SqlCommand.DebugForceAsyncWriteDelay, Timeout.Infinite); task = completion.Task; } #endif else { if (_parser.MARSOn) { // Only take reset lock on MARS. CheckSetResetConnectionState(sniError, CallbackType.Write); } if (sniError == TdsEnums.SNI_SUCCESS) { _lastSuccessfulIOTimer._value = DateTime.UtcNow.Ticks; if (!sync) { // Since there will be no callback, remove the packet from the pending list Debug.Assert(packetPointer != IntPtr.Zero, "Packet added to list has an invalid pointer, can not remove from pending list"); RemovePacketFromPendingList(packetPointer); } } else { AddError(_parser.ProcessSNIError(this)); ThrowExceptionAndWarning(callerHasConnectionLock); } AssertValidState(); } return task; }
internal static uint SNIWritePacket(SNIHandle pConn, SNIPacket packet, bool sync) { if (sync) { return SNIWriteSyncOverAsync(pConn, packet); } else { return SNIWriteAsyncWrapper(pConn, packet); } }
#pragma warning restore 0420 // Sends an attention signal - executing thread will consume attn. internal void SendAttention(bool mustTakeWriteLock = false) { if (!_attentionSent) { // Dumps contents of buffer to OOB write (currently only used for // attentions. There is no body for this message // Doesn't touch this._outBytesUsed if (_parser.State == TdsParserState.Closed || _parser.State == TdsParserState.Broken) { return; } SNIPacket attnPacket = new SNIPacket(Handle); _sniAsyncAttnPacket = attnPacket; SNINativeMethodWrapper.SNIPacketSetData(attnPacket, SQL.AttentionHeader, TdsEnums.HEADER_LEN); try { // Dev11 #344723: SqlClient stress hang System_Data!Tcp::ReadSync via a call to SqlDataReader::Close // Set _attentionSending to true before sending attention and reset after setting _attentionSent // This prevents a race condition between receiving the attention ACK and setting _attentionSent _attentionSending = true; #if DEBUG if (!_skipSendAttention) { #endif // Take lock and send attention bool releaseLock = false; if ((mustTakeWriteLock) && (!_parser.Connection.ThreadHasParserLockForClose)) { releaseLock = true; _parser.Connection._parserLock.Wait(canReleaseFromAnyThread: false); _parser.Connection.ThreadHasParserLockForClose = true; } try { // Check again (just in case the connection was closed while we were waiting) if (_parser.State == TdsParserState.Closed || _parser.State == TdsParserState.Broken) { return; } UInt32 sniError; _parser._asyncWrite = false; // stop async write SNIWritePacket(Handle, attnPacket, out sniError, canAccumulate: false, callerHasConnectionLock: false); } finally { if (releaseLock) { _parser.Connection.ThreadHasParserLockForClose = false; _parser.Connection._parserLock.Release(); } } #if DEBUG } #endif SetTimeoutSeconds(AttentionTimeoutSeconds); // Initialize new attention timeout of 5 seconds. _attentionSent = true; } finally { _attentionSending = false; } AssertValidState(); } }
internal void SendAttention() { if (!this._attentionSent && ((this._parser.State != TdsParserState.Closed) && (this._parser.State != TdsParserState.Broken))) { uint num; SNIPacket packet = new SNIPacket(this.Handle); if (this._parser.AsyncOn) { this._sniAsyncAttnPacket = packet; if (this._asyncAttentionResult == null) { this._asyncAttentionResult = new DbAsyncResult(this._parser, string.Empty, null, null, null); } } else { this._sniAsyncAttnPacket = null; } SNINativeMethodWrapper.SNIPacketSetData(packet, SQL.AttentionHeader, 8); if (this._parser.AsyncOn) { num = this.SNIWriteAsync(this.Handle, packet, this._asyncAttentionResult); Bid.Trace("<sc.TdsParser.SendAttention|Info> Send Attention ASync .\n"); } else { num = SNINativeMethodWrapper.SNIWriteSync(this.Handle, packet); Bid.Trace("<sc.TdsParser.SendAttention|Info> Send Attention Sync.\n"); if (num != 0) { Bid.Trace("<sc.TdsParser.SendAttention|Info> SNIWriteSync returned error code %d\n", (int) num); this._parser.Errors.Add(this._parser.ProcessSNIError(this)); this._parser.ThrowExceptionAndWarning(); } } this.SetTimeoutSeconds(5); this._attentionSent = true; if (Bid.AdvancedOn) { Bid.TraceBin("<sc.TdsParser.WritePacket|INFO|ADV> Packet sent", this._outBuff, (ushort) this._outBytesUsed); } Bid.Trace("<sc.TdsParser.SendAttention|Info> Attention sent to the server.\n"); } }
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 uint SNIWriteAsync(SNIHandle handle, SNIPacket packet, DbAsyncResult asyncResult) { uint num; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { this.IncrementPendingCallbacks(); num = SNINativeMethodWrapper.SNIWriteAsync(handle, packet); if ((num == 0) || (num != 0x3e5)) { this.DecrementPendingCallbacks(false); } } if (num != 0) { if (num != 0x3e5) { Bid.Trace("<sc.TdsParser.WritePacket|Info> write async returned error code %d\n", (int) num); this._parser.Errors.Add(this._parser.ProcessSNIError(this)); this.ThrowExceptionAndWarning(); return num; } if (num != 0x3e5) { return num; } try { ((IAsyncResult) asyncResult).AsyncWaitHandle.WaitOne(); if (this._error != null) { this._parser.Errors.Add(this._error); this._error = null; Bid.Trace("<sc.TdsParser.WritePacket|Info> write async returned error code %d\n", (int) num); this.ThrowExceptionAndWarning(); } } finally { asyncResult.Reset(); } } return num; }
internal void Dispose() { SafeHandle packetHandle = _sniPacket; SafeHandle sessionHandle = _sessionHandle; SafeHandle asyncAttnPacket = _sniAsyncAttnPacket; _sniPacket = null; _sessionHandle = null; _sniAsyncAttnPacket = null; Timer networkPacketTimeout = _networkPacketTimeout; if (networkPacketTimeout != null) { _networkPacketTimeout = null; networkPacketTimeout.Dispose(); } Debug.Assert(Volatile.Read(ref _readingCount) >= 0, "_readingCount is negative"); if (Volatile.Read(ref _readingCount) > 0) { // if _reading is true, we need to wait for it to complete // if _reading is false, then future read attempts will // already see the null _sessionHandle and abort. // We block after nulling _sessionHandle but before disposing it // to give a chance for a read that has already grabbed the // handle to complete. SpinWait.SpinUntil(() => Volatile.Read(ref _readingCount) == 0); } if (null != sessionHandle || null != packetHandle) { try { } finally { if (packetHandle != null) { packetHandle.Dispose(); } if (asyncAttnPacket != null) { asyncAttnPacket.Dispose(); } if (sessionHandle != null) { sessionHandle.Dispose(); DecrementPendingCallbacks(true); // Will dispose of GC handle. } } } if (_writePacketCache != null) { lock (_writePacketLockObject) { try { } finally { _writePacketCache.Dispose(); // Do not set _writePacketCache to null, just in case a WriteAsyncCallback completes after this point } } } }
public static uint SNIWritePacket (SafeHandle handle, SNIPacket packet, bool sync) { throw new NotSupportedException (msg); }