internal void Commit() { if (_innerConnection.IsLockedForBulkCopy) { throw SQL.ConnectionLockedForBcpEvent(); } _innerConnection.ValidateConnectionForExecute(null); // If this transaction has been completed, throw exception since it is unusable. try { // COMMIT ignores transaction names, and so there is no reason to pass it anything. COMMIT // simply commits the transaction from the most recent BEGIN, nested or otherwise. _innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Commit, null, IsolationLevel.Unspecified, null, false); { ZombieParent(); } } catch (Exception e) { if (ADP.IsCatchableExceptionType(e)) { CheckTransactionLevelAndZombie(); } throw; } }
internal void Commit() { IntPtr hscp; Bid.ScopeEnter(out hscp, "<sc.SqlInternalTransaction.Commit|API> %d#", ObjectID); if (_innerConnection.IsLockedForBulkCopy) { throw SQL.ConnectionLockedForBcpEvent(); } _innerConnection.ValidateConnectionForExecute(null); try { // If this transaction has been completed, throw exception since it is unusable. try { // COMMIT ignores transaction names, and so there is no reason to pass it anything. COMMIT // simply commits the transaction from the most recent BEGIN, nested or otherwise. _innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Commit, null, IsolationLevel.Unspecified, null, false); // SQL BU DT 291159 - perform full Zombie on pre-Yukon, but do not actually // complete internal transaction until informed by server in the case of Yukon // or later. if (!IsZombied && !_innerConnection.IsYukonOrNewer) { // Since nested transactions are no longer allowed, set flag to false. // This transaction has been completed. Zombie(); } else { ZombieParent(); } } catch (Exception e) { // if (ADP.IsCatchableExceptionType(e)) { CheckTransactionLevelAndZombie(); } throw; } } finally { Bid.ScopeLeave(ref hscp); } }
internal void CloseFromConnection() { SqlInternalConnection innerConnection = _innerConnection; Debug.Assert(innerConnection != null, "How can we be here if the connection is null?"); bool processFinallyBlock = true; try { innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.IfRollback, null, IsolationLevel.Unspecified, null, false); } catch (Exception e) { processFinallyBlock = ADP.IsCatchableExceptionType(e); throw; } finally { if (processFinallyBlock) { // Always ensure we're zombied; Yukon will send an EnvChange that // will cause the zombie, but only if we actually go to the wire; // Sphinx and Shiloh won't send the env change, so we have to handle // them ourselves. Zombie(); } } }
internal void CloseFromConnection() { SqlInternalConnection innerConnection = _innerConnection; Debug.Assert(innerConnection != null, "How can we be here if the connection is null?"); Bid.PoolerTrace("<sc.SqlInteralTransaction.CloseFromConnection|RES|CPOOL> %d#, Closing\n", ObjectID); bool processFinallyBlock = true; try { innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.IfRollback, null, IsolationLevel.Unspecified, null, false); } catch (Exception e) { processFinallyBlock = ADP.IsCatchableExceptionType(e); throw; } finally { TdsParser.ReliabilitySection.Assert("unreliable call to CloseFromConnection"); // you need to setup for a thread abort somewhere before you call this method if (processFinallyBlock) { // Always ensure we're zombied; Yukon will send an EnvChange that // will cause the zombie, but only if we actually go to the wire; // Sphinx and Shiloh won't send the env change, so we have to handle // them ourselves. Zombie(); } } }
public void Initialize() { // if we get here, then we know for certain that we're the delegated // transaction. SqlInternalConnection connection = _connection; SqlConnection usersConnection = connection.Connection; Bid.Trace("<sc.SqlDelegatedTransaction.Initialize|RES|CPOOL> %d#, Connection %d#, delegating transaction.\n", ObjectID, connection.ObjectID); RuntimeHelpers.PrepareConstrainedRegions(); try { #if DEBUG TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); RuntimeHelpers.PrepareConstrainedRegions(); try { tdsReliabilitySection.Start(); #else { #endif //DEBUG if (connection.IsEnlistedInTransaction) // defect first { Bid.Trace("<sc.SqlDelegatedTransaction.Initialize|RES|CPOOL> %d#, Connection %d#, was enlisted, now defecting.\n", ObjectID, connection.ObjectID); connection.EnlistNull(); } _internalTransaction = new SqlInternalTransaction(connection, TransactionType.Delegated, null); connection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Begin, null, _isolationLevel, _internalTransaction, true); // Handle case where ExecuteTran didn't produce a new transaction, but also didn't throw. if (null == connection.CurrentTransaction) { connection.DoomThisConnection(); throw ADP.InternalError(ADP.InternalErrorCode.UnknownTransactionFailure); } _active = true; } #if DEBUG finally { tdsReliabilitySection.Stop(); } #endif //DEBUG } catch (System.OutOfMemoryException e) { usersConnection.Abort(e); throw; } catch (System.StackOverflowException e) { usersConnection.Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { usersConnection.Abort(e); throw; } }
public byte[] Promote() { Exception exception; SqlInternalConnection validConnection = this.GetValidConnection(); byte[] promotedDTCToken = null; SqlConnection connection = validConnection.Connection; Bid.Trace("<sc.SqlDelegatedTransaction.Promote|RES|CPOOL> %d#, Connection %d#, promoting transaction.\n", this.ObjectID, validConnection.ObjectID); RuntimeHelpers.PrepareConstrainedRegions(); try { lock (validConnection) { try { this.ValidateActiveOnConnection(validConnection); validConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Promote, null, System.Data.IsolationLevel.Unspecified, this._internalTransaction, true); promotedDTCToken = this._connection.PromotedDTCToken; exception = null; } catch (SqlException exception3) { exception = exception3; ADP.TraceExceptionWithoutRethrow(exception3); validConnection.DoomThisConnection(); } catch (InvalidOperationException exception2) { exception = exception2; ADP.TraceExceptionWithoutRethrow(exception2); validConnection.DoomThisConnection(); } } } catch (OutOfMemoryException exception6) { connection.Abort(exception6); throw; } catch (StackOverflowException exception5) { connection.Abort(exception5); throw; } catch (ThreadAbortException exception4) { connection.Abort(exception4); throw; } if (exception != null) { throw SQL.PromotionFailed(exception); } return(promotedDTCToken); }
public void Rollback(SinglePhaseEnlistment enlistment) { SqlInternalConnection validConnection = this.GetValidConnection(); SqlConnection connection = validConnection.Connection; Bid.Trace("<sc.SqlDelegatedTransaction.Rollback|RES|CPOOL> %d#, Connection %d#, aborting transaction.\n", this.ObjectID, validConnection.ObjectID); RuntimeHelpers.PrepareConstrainedRegions(); try { lock (validConnection) { try { this.ValidateActiveOnConnection(validConnection); this._active = false; this._connection = null; validConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Rollback, null, System.Data.IsolationLevel.Unspecified, this._internalTransaction, true); } catch (SqlException exception5) { ADP.TraceExceptionWithoutRethrow(exception5); validConnection.DoomThisConnection(); } catch (InvalidOperationException exception4) { ADP.TraceExceptionWithoutRethrow(exception4); validConnection.DoomThisConnection(); } } validConnection.CleanupConnectionOnTransactionCompletion(this._atomicTransaction); enlistment.Aborted(); } catch (OutOfMemoryException exception3) { connection.Abort(exception3); throw; } catch (StackOverflowException exception2) { connection.Abort(exception2); throw; } catch (ThreadAbortException exception) { connection.Abort(exception); throw; } }
public void Initialize() { // if we get here, then we know for certain that we're the delegated // transaction. SqlInternalConnection connection = _connection; SqlConnection usersConnection = connection.Connection; RuntimeHelpers.PrepareConstrainedRegions(); try { if (connection.IsEnlistedInTransaction) { // defect first connection.EnlistNull(); } _internalTransaction = new SqlInternalTransaction(connection, TransactionType.Delegated, null); connection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Begin, null, _isolationLevel, _internalTransaction, true); // Handle case where ExecuteTran didn't produce a new transaction, but also didn't throw. if (null == connection.CurrentTransaction) { connection.DoomThisConnection(); throw ADP.InternalError(ADP.InternalErrorCode.UnknownTransactionFailure); } _active = true; } catch (System.OutOfMemoryException e) { usersConnection.Abort(e); throw; } catch (System.StackOverflowException e) { usersConnection.Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { usersConnection.Abort(e); throw; } }
public void Initialize() { SqlInternalConnection innerConnection = this._connection; SqlConnection connection = innerConnection.Connection; Bid.Trace("<sc.SqlDelegatedTransaction.Initialize|RES|CPOOL> %d#, Connection %d#, delegating transaction.\n", this.ObjectID, innerConnection.ObjectID); RuntimeHelpers.PrepareConstrainedRegions(); try { if (innerConnection.IsEnlistedInTransaction) { Bid.Trace("<sc.SqlDelegatedTransaction.Initialize|RES|CPOOL> %d#, Connection %d#, was enlisted, now defecting.\n", this.ObjectID, innerConnection.ObjectID); innerConnection.EnlistNull(); } this._internalTransaction = new SqlInternalTransaction(innerConnection, TransactionType.Delegated, null); innerConnection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Begin, null, this._isolationLevel, this._internalTransaction, true); if (innerConnection.CurrentTransaction == null) { innerConnection.DoomThisConnection(); throw ADP.InternalError(ADP.InternalErrorCode.UnknownTransactionFailure); } this._active = true; } catch (OutOfMemoryException exception3) { connection.Abort(exception3); throw; } catch (StackOverflowException exception2) { connection.Abort(exception2); throw; } catch (ThreadAbortException exception) { connection.Abort(exception); throw; } }
internal void CloseFromConnection() { SqlInternalConnection connection = this._innerConnection; Bid.PoolerTrace("<sc.SqlInteralTransaction.CloseFromConnection|RES|CPOOL> %d#, Closing\n", this.ObjectID); bool flag = true; try { connection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.IfRollback, null, IsolationLevel.Unspecified, null, false); } catch (Exception exception) { flag = ADP.IsCatchableExceptionType(exception); throw; } finally { if (flag) { this.Zombie(); } } }
// Called by the transaction to initiate commit sequence public void SinglePhaseCommit(SinglePhaseEnlistment enlistment) { Debug.Assert(null != enlistment, "null enlistment?"); SqlInternalConnection connection = GetValidConnection(); SqlConnection usersConnection = connection.Connection; RuntimeHelpers.PrepareConstrainedRegions(); try { // If the connection is dooomed, we can be certain that the // transaction will eventually be rolled back, and we shouldn't // attempt to commit it. if (connection.IsConnectionDoomed) { lock (connection) { _active = false; // set to inactive first, doesn't matter how the rest completes, this transaction is done. _connection = null; } enlistment.Aborted(SQL.ConnectionDoomed()); } else { Exception commitException; lock (connection) { try { // Now that we've acquired the lock, make sure we still have valid state for this operation. ValidateActiveOnConnection(connection); _active = false; // set to inactive first, doesn't matter how the rest completes, this transaction is done. _connection = null; // Set prior to ExecuteTransaction call in case this initiates a TransactionEnd event connection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Commit, null, IsolationLevel.Unspecified, _internalTransaction, true); commitException = null; } catch (SqlException e) { commitException = e; // Doom the connection, to make sure that the transaction is // eventually rolled back. // VSTS 144562: doom the connection while having the lock on it to prevent race condition with "Transaction Ended" Event connection.DoomThisConnection(); } catch (InvalidOperationException e) { commitException = e; connection.DoomThisConnection(); } } if (commitException != null) { // connection.ExecuteTransaction failed with exception if (_internalTransaction.IsCommitted) { // Even though we got an exception, the transaction // was committed by the server. enlistment.Committed(); } else if (_internalTransaction.IsAborted) { // The transaction was aborted, report that to // SysTx. enlistment.Aborted(commitException); } else { // The transaction is still active, we cannot // know the state of the transaction. enlistment.InDoubt(commitException); } // We eat the exception. This is called on the SysTx // thread, not the applications thread. If we don't // eat the exception an UnhandledException will occur, // causing the process to FailFast. } connection.CleanupConnectionOnTransactionCompletion(_atomicTransaction); if (commitException == null) { // connection.ExecuteTransaction succeeded enlistment.Committed(); } } } catch (System.OutOfMemoryException e) { usersConnection.Abort(e); throw; } catch (System.StackOverflowException e) { usersConnection.Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { usersConnection.Abort(e); throw; } }
// Called by transaction to initiate abort sequence public void Rollback(SinglePhaseEnlistment enlistment) { Debug.Assert(null != enlistment, "null enlistment?"); SqlInternalConnection connection = GetValidConnection(); SqlConnection usersConnection = connection.Connection; RuntimeHelpers.PrepareConstrainedRegions(); try { lock (connection) { try { // Now that we've acquired the lock, make sure we still have valid state for this operation. ValidateActiveOnConnection(connection); _active = false; // set to inactive first, doesn't matter how the execute completes, this transaction is done. _connection = null; // Set prior to ExecuteTransaction call in case this initiates a TransactionEnd event // If we haven't already rolled back (or aborted) then tell the SQL Server to roll back if (!_internalTransaction.IsAborted) { connection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Rollback, null, IsolationLevel.Unspecified, _internalTransaction, true); } } catch (SqlException) { // Doom the connection, to make sure that the transaction is // eventually rolled back. // VSTS 144562: doom the connection while having the lock on it to prevent race condition with "Transaction Ended" Event connection.DoomThisConnection(); // Unlike SinglePhaseCommit, a rollback is a rollback, regardless // of how it happens, so SysTx won't throw an exception, and we // don't want to throw an exception either, because SysTx isn't // handling it and it may create a fail fast scenario. In the end, // there is no way for us to communicate to the consumer that this // failed for more serious reasons than usual. // // This is a bit like "should you throw if Close fails", however, // it only matters when you really need to know. In that case, // we have the tracing that we're doing to fallback on for the // investigation. } catch (InvalidOperationException) { connection.DoomThisConnection(); } } // it doesn't matter whether the rollback succeeded or not, we presume // that the transaction is aborted, because it will be eventually. connection.CleanupConnectionOnTransactionCompletion(_atomicTransaction); enlistment.Aborted(); } catch (System.OutOfMemoryException e) { usersConnection.Abort(e); throw; } catch (System.StackOverflowException e) { usersConnection.Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { usersConnection.Abort(e); throw; } }
public byte[] Promote() { // Operations that might be affected by multi-threaded use MUST be done inside the lock. // Don't read values off of the connection outside the lock unless it doesn't really matter // from an operational standpoint (i.e. logging connection's ObjectID should be fine, // but the PromotedDTCToken can change over calls. so that must be protected). SqlInternalConnection connection = GetValidConnection(); Exception promoteException; byte[] returnValue = null; SqlConnection usersConnection = connection.Connection; RuntimeHelpers.PrepareConstrainedRegions(); try { lock (connection) { try { // Now that we've acquired the lock, make sure we still have valid state for this operation. ValidateActiveOnConnection(connection); connection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Promote, null, IsolationLevel.Unspecified, _internalTransaction, true); returnValue = _connection.PromotedDTCToken; // For Global Transactions, we need to set the Transaction Id since we use a Non-MSDTC Promoter type. if (_connection.IsGlobalTransaction) { if (SysTxForGlobalTransactions.SetDistributedTransactionIdentifier == null) { throw SQL.UnsupportedSysTxForGlobalTransactions(); } if (!_connection.IsGlobalTransactionsEnabledForServer) { throw SQL.GlobalTransactionsNotEnabled(); } SysTxForGlobalTransactions.SetDistributedTransactionIdentifier.Invoke(_atomicTransaction, new object[] { this, GetGlobalTxnIdentifierFromToken() }); } promoteException = null; } catch (SqlException e) { promoteException = e; // Doom the connection, to make sure that the transaction is // eventually rolled back. // VSTS 144562: doom the connection while having the lock on it to prevent race condition with "Transaction Ended" Event connection.DoomThisConnection(); } catch (InvalidOperationException e) { promoteException = e; connection.DoomThisConnection(); } } } catch (System.OutOfMemoryException e) { usersConnection.Abort(e); throw; } catch (System.StackOverflowException e) { usersConnection.Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { usersConnection.Abort(e); throw; } if (promoteException != null) { throw SQL.PromotionFailed(promoteException); } return(returnValue); }
public Byte [] Promote() { // Operations that might be affected by multi-threaded use MUST be done inside the lock. // Don't read values off of the connection outside the lock unless it doesn't really matter // from an operational standpoint (i.e. logging connection's ObjectID should be fine, // but the PromotedDTCToken can change over calls. so that must be protected). SqlInternalConnection connection = GetValidConnection(); Exception promoteException; byte[] returnValue = null; SqlConnection usersConnection = connection.Connection; Bid.Trace("<sc.SqlDelegatedTransaction.Promote|RES|CPOOL> %d#, Connection %d#, promoting transaction.\n", ObjectID, connection.ObjectID); RuntimeHelpers.PrepareConstrainedRegions(); try { #if DEBUG TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); RuntimeHelpers.PrepareConstrainedRegions(); try { tdsReliabilitySection.Start(); #else { #endif //DEBUG lock (connection) { try { // Now that we've acquired the lock, make sure we still have valid state for this operation. ValidateActiveOnConnection(connection); connection.ExecuteTransaction(SqlInternalConnection.TransactionRequest.Promote, null, IsolationLevel.Unspecified, _internalTransaction, true); returnValue = _connection.PromotedDTCToken; promoteException = null; } catch (SqlException e) { promoteException = e; ADP.TraceExceptionWithoutRethrow(e); // Doom the connection, to make sure that the transaction is // eventually rolled back. // VSTS 144562: doom the connection while having the lock on it to prevent race condition with "Transaction Ended" Event connection.DoomThisConnection(); } catch (InvalidOperationException e) { promoteException = e; ADP.TraceExceptionWithoutRethrow(e); connection.DoomThisConnection(); } } } #if DEBUG finally { tdsReliabilitySection.Stop(); } #endif //DEBUG } catch (System.OutOfMemoryException e) { usersConnection.Abort(e); throw; } catch (System.StackOverflowException e) { usersConnection.Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { usersConnection.Abort(e); throw; } if (promoteException != null) { throw SQL.PromotionFailed(promoteException); } return(returnValue); }