internal static Transaction FastGetTransaction(TransactionScope currentScope, ContextData contextData, out Transaction contextTransaction) { Transaction current = null; contextTransaction = null; contextTransaction = contextData.CurrentTransaction; switch (InteropMode(currentScope)) { case EnterpriseServicesInteropOption.None: current = contextTransaction; // If there is a transaction in the execution context or if there is a current transaction scope // then honer the transaction context. if (current == null && currentScope == null) { // Otherwise check for an external current. if (TransactionManager.s_currentDelegateSet) { current = TransactionManager.s_currentDelegate(); } else { current = EnterpriseServices.GetContextTransaction(contextData); } } break; case EnterpriseServicesInteropOption.Full: current = EnterpriseServices.GetContextTransaction(contextData); break; case EnterpriseServicesInteropOption.Automatic: if (EnterpriseServices.UseServiceDomainForCurrent()) { current = EnterpriseServices.GetContextTransaction(contextData); } else { current = contextData.CurrentTransaction; } break; } return current; }
internal static Transaction?FastGetTransaction(TransactionScope?currentScope, ContextData contextData, out Transaction?contextTransaction) { Transaction?current = null; contextTransaction = null; contextTransaction = contextData.CurrentTransaction; switch (InteropMode(currentScope)) { case EnterpriseServicesInteropOption.None: current = contextTransaction; // If there is a transaction in the execution context or if there is a current transaction scope // then honer the transaction context. if (current == null && currentScope == null) { // Otherwise check for an external current. if (TransactionManager.s_currentDelegateSet) { current = TransactionManager.s_currentDelegate !(); } else { current = EnterpriseServices.GetContextTransaction(contextData); } } break; case EnterpriseServicesInteropOption.Full: current = EnterpriseServices.GetContextTransaction(contextData); break; case EnterpriseServicesInteropOption.Automatic: if (EnterpriseServices.UseServiceDomainForCurrent()) { current = EnterpriseServices.GetContextTransaction(contextData); } else { current = contextData.CurrentTransaction; } break; } return(current); }
// GetContextTransaction // // Get a transaction from Com+ through EnterpriseServices internal static Transaction GetContextTransaction(ContextData contextData) { if (EnterpriseServicesOk) { return JitSafeGetContextTransaction(contextData); } return null; }
private static Transaction JitSafeGetContextTransaction(ContextData contextData) { // Attempt to see if we are in the default context in which case we don't need to // call SystemTransaction at all. SafeIUnknown defaultContext = null; if (contextData.WeakDefaultComContext != null) { defaultContext = (SafeIUnknown)contextData.WeakDefaultComContext.Target; } if (contextData.DefaultComContextState == DefaultComContextState.Unknown || (contextData.DefaultComContextState == DefaultComContextState.Available && defaultContext == null) ) { try { NativeMethods.CoGetDefaultContext(-1, ref IID_IObjContext, out defaultContext); contextData.WeakDefaultComContext = new WeakReference(defaultContext); contextData.DefaultComContextState = DefaultComContextState.Available; } catch (System.EntryPointNotFoundException e) { if (DiagnosticTrace.Verbose) { ExceptionConsumedTraceRecord.Trace(SR.GetString(SR.TraceSourceBase), e); } contextData.DefaultComContextState = DefaultComContextState.Unavailable; } } if (contextData.DefaultComContextState == DefaultComContextState.Available) { IntPtr contextToken = IntPtr.Zero; NativeMethods.CoGetContextToken(out contextToken); // Check to see if the context token is the default context. if (defaultContext.DangerousGetHandle() == contextToken) { return null; } } #if USE_ISINTRANSACTION if (!SysES.ContextUtil.IsInTransaction) { return null; } #endif return (Transaction)SysES.ContextUtil.SystemTransaction; }
static public bool TryGetCurrentData(out ContextData currentData) { currentData = null; ContextKey contextKey = (ContextKey)CallContext.LogicalGetData(CurrentTransactionProperty); if (contextKey == null) { return false; } else { return ContextDataTable.TryGetValue(contextKey, out currentData); } }
internal static void GetCurrentTransactionAndScope(out Transaction current, out TransactionScope currentScope, out ContextData contextData, out Transaction contextTransaction) { contextData = ContextData.CurrentData; currentScope = contextData.CurrentScope; current = FastGetTransaction(currentScope, contextData, out contextTransaction); }
public static bool TryGetCurrentData(out ContextData currentData) { currentData = null; ContextKey contextKey = s_currentTransaction.Value; if (contextKey == null) { return false; } else { return s_contextDataTable.TryGetValue(contextKey, out currentData); } }
private static Transaction JitSafeGetContextTransaction(ContextData contextData) { SafeIUnknown safeUnknown = null; if (contextData.WeakDefaultComContext != null) { safeUnknown = (SafeIUnknown) contextData.WeakDefaultComContext.Target; } if ((contextData.DefaultComContextState == DefaultComContextState.Unknown) || ((contextData.DefaultComContextState == DefaultComContextState.Available) && (safeUnknown == null))) { try { System.Transactions.NativeMethods.CoGetDefaultContext(-1, ref IID_IObjContext, out safeUnknown); contextData.WeakDefaultComContext = new WeakReference(safeUnknown); contextData.DefaultComContextState = DefaultComContextState.Available; } catch (EntryPointNotFoundException exception) { if (DiagnosticTrace.Verbose) { ExceptionConsumedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), exception); } contextData.DefaultComContextState = DefaultComContextState.Unavailable; } } if (contextData.DefaultComContextState == DefaultComContextState.Available) { IntPtr zero = IntPtr.Zero; System.Transactions.NativeMethods.CoGetContextToken(out zero); if (safeUnknown.DangerousGetHandle() == zero) { return null; } } if (!ContextUtil.IsInTransaction) { return null; } return ContextUtil.SystemTransaction; }
internal static Transaction FastGetTransaction(TransactionScope currentScope, ContextData contextData, out Transaction contextTransaction) { Transaction transaction = null; contextTransaction = null; contextTransaction = contextData.CurrentTransaction; switch (InteropMode(currentScope)) { case EnterpriseServicesInteropOption.None: transaction = contextTransaction; if ((transaction == null) && (currentScope == null)) { if (!TransactionManager.currentDelegateSet) { return(GetContextTransaction(contextData)); } transaction = TransactionManager.currentDelegate(); } return(transaction); case EnterpriseServicesInteropOption.Automatic: if (!UseServiceDomainForCurrent()) { return(contextData.CurrentTransaction); } return(GetContextTransaction(contextData)); case EnterpriseServicesInteropOption.Full: return(GetContextTransaction(contextData)); } return(transaction); }
internal static void GetCurrentTransactionAndScope(out Transaction current, out TransactionScope currentScope, out ContextData contextData, out Transaction contextTransaction) { contextData = ContextData.CurrentData; currentScope = contextData.CurrentScope; current = FastGetTransaction(currentScope, contextData, out contextTransaction); }
internal static Transaction FastGetTransaction(TransactionScope currentScope, ContextData contextData, out Transaction contextTransaction) { Transaction transaction = null; contextTransaction = null; contextTransaction = contextData.CurrentTransaction; switch (InteropMode(currentScope)) { case EnterpriseServicesInteropOption.None: transaction = contextTransaction; if ((transaction == null) && (currentScope == null)) { if (!TransactionManager.currentDelegateSet) { return GetContextTransaction(contextData); } transaction = TransactionManager.currentDelegate(); } return transaction; case EnterpriseServicesInteropOption.Automatic: if (!UseServiceDomainForCurrent()) { return contextData.CurrentTransaction; } return GetContextTransaction(contextData); case EnterpriseServicesInteropOption.Full: return GetContextTransaction(contextData); } return transaction; }
private void SaveTLSContextData() { if (_savedTLSContextData == null) { _savedTLSContextData = new ContextData(false); } _savedTLSContextData.CurrentScope = ContextData.TLSCurrentData.CurrentScope; _savedTLSContextData.CurrentTransaction = ContextData.TLSCurrentData.CurrentTransaction; _savedTLSContextData.DefaultComContextState = ContextData.TLSCurrentData.DefaultComContextState; _savedTLSContextData.WeakDefaultComContext = ContextData.TLSCurrentData.WeakDefaultComContext; }
// PopScope // // Pop the current transaction scope off the top of the stack private void PopScope() { bool shouldRestoreContextData = true; // Clear the current TransactionScope CallContext data if (AsyncFlowEnabled) { CallContextCurrentData.ClearCurrentData(ContextKey, true); } if (_scopeThread == Thread.CurrentThread) { // async function yield at await points and main thread can continue execution. We need to make sure the TLS data are restored appropriately. // Restore the TLS only if the thread Ids match. RestoreSavedTLSContextData(); } // Restore threadContextData to parent CallContext or TLS data if (_savedCurrentScope != null) { if (_savedCurrentScope.AsyncFlowEnabled) { _threadContextData = CallContextCurrentData.CreateOrGetCurrentData(_savedCurrentScope.ContextKey); } else { if (_savedCurrentScope._scopeThread != Thread.CurrentThread) { // Clear TLS data so that transaction doesn't leak from current thread. shouldRestoreContextData = false; ContextData.TLSCurrentData = null; } else { _threadContextData = ContextData.TLSCurrentData; } CallContextCurrentData.ClearCurrentData(_savedCurrentScope.ContextKey, false); } } else { // No parent TransactionScope present // Clear any CallContext data CallContextCurrentData.ClearCurrentData(null, false); if (_scopeThread != Thread.CurrentThread) { // Clear TLS data so that transaction doesn't leak from current thread. shouldRestoreContextData = false; ContextData.TLSCurrentData = null; } else { // Restore the current data to TLS. ContextData.TLSCurrentData = _threadContextData; } } // prevent restoring the context in an unexpected thread due to thread switch during TransactionScope's Dispose if (shouldRestoreContextData) { _threadContextData.CurrentScope = _savedCurrentScope; RestoreCurrent(); } }
// PushScope // // Push a transaction scope onto the stack. private void PushScope() { // Fixup the interop mode before we set current. if (!_interopModeSpecified) { // Transaction.InteropMode will take the interop mode on // for the scope in currentScope into account. _interopOption = Transaction.InteropMode(_savedCurrentScope); } // async function yield at await points and main thread can continue execution. We need to make sure the TLS data are restored appropriately. SaveTLSContextData(); if (AsyncFlowEnabled) { // Async Flow is enabled and CallContext will be used for ambient transaction. _threadContextData = CallContextCurrentData.CreateOrGetCurrentData(ContextKey); if (_savedCurrentScope == null && _savedCurrent == null) { // Clear TLS data so that transaction doesn't leak from current thread. ContextData.TLSCurrentData = null; } } else { // Legacy TransactionScope. Use TLS to track ambient transaction context. _threadContextData = ContextData.TLSCurrentData; CallContextCurrentData.ClearCurrentData(ContextKey, false); } // This call needs to be done first SetCurrent(_expectedCurrent); _threadContextData.CurrentScope = this; }