Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / tx / System / Transactions / TransactionManager.cs / 1305376 / TransactionManager.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Configuration; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Security; using System.Security.Permissions; using System.Threading; using System.Transactions.Configuration; using System.Transactions.Diagnostics; using System.Xml; using System.Xml.Serialization; [assembly:BestFitMapping(false)] #pragma warning disable 618 [assembly:SecurityPermissionAttribute(SecurityAction.RequestMinimum)] #pragma warning restore 618 // No external data is ever passed to PrivilegedConfigurationManager.GetSection [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Configuration.PrivilegedConfigurationManager.GetSection(System.String):System.Object")] namespace System.Transactions { public delegate Transaction HostCurrentTransactionCallback(); public delegate void TransactionStartedEventHandler(object sender, TransactionEventArgs e); public static class TransactionManager { // Revovery Information Version private const Int32 recoveryInformationVersion1 = 1; private const Int32 currentRecoveryVersion = recoveryInformationVersion1; // Record if the platform has been validated. internal static bool _platformValidated; // Hashtable of promoted transactions, keyed by identifier guid. This is used by // FindPromotedTransaction to support transaction equivalence when a transaction is // serialized and then deserialized back in this app-domain. private static Hashtable promotedTransactionTable; // Sorted Table of transaction timeouts private static TransactionTable transactionTable; private static TransactionStartedEventHandler distributedTransactionStartedDelegate; public static event TransactionStartedEventHandler DistributedTransactionStarted { [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] add { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); lock( ClassSyncObject ) { TransactionManager.distributedTransactionStartedDelegate = (TransactionStartedEventHandler)System.Delegate.Combine(TransactionManager.distributedTransactionStartedDelegate, value); if( value != null ) { ProcessExistingTransactions( value ); } } } [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] remove { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); lock ( ClassSyncObject ) { TransactionManager.distributedTransactionStartedDelegate = (TransactionStartedEventHandler)System.Delegate.Remove (TransactionManager.distributedTransactionStartedDelegate, value); } } } internal static void ProcessExistingTransactions( TransactionStartedEventHandler eventHandler ) { lock( PromotedTransactionTable ) { foreach( DictionaryEntry entry in PromotedTransactionTable ) { WeakReference weakRef = (WeakReference)entry.Value; Transaction tx = (Transaction)weakRef.Target; if( tx != null ) { TransactionEventArgs args = new TransactionEventArgs(); args.transaction = tx.InternalClone(); eventHandler( args.transaction, args ); } } } } internal static void FireDistributedTransactionStarted( Transaction transaction ) { TransactionStartedEventHandler localStartedEventHandler = null; lock( ClassSyncObject ) { localStartedEventHandler = TransactionManager.distributedTransactionStartedDelegate; } if ( null != localStartedEventHandler ) { TransactionEventArgs args = new TransactionEventArgs(); args.transaction = transaction.InternalClone(); localStartedEventHandler(args.transaction, args); } } // Data storage for current delegate internal static HostCurrentTransactionCallback currentDelegate = null; internal static bool currentDelegateSet = false; // CurrentDelegate // // Store a delegate to be used to query for an external current transaction. public static HostCurrentTransactionCallback HostCurrentCallback { // get_HostCurrentCallback is used from get_CurrentTransaction, which doesn't have any permission requirements. // We don't expose what is returned from this property in that case. But we don't want just anybody being able // to retrieve the value. [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] get { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); // Note do not add trace notifications to this method. It is called // at the startup of SQLCLR and tracing has too much working set overhead. return currentDelegate; } [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] set { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); // Note do not add trace notifications to this method. It is called // at the startup of SQLCLR and tracing has too much working set overhead. if( value == null ) { throw new ArgumentNullException( "value" ); } lock( ClassSyncObject ) { if( currentDelegateSet ) { throw new InvalidOperationException( SR.GetString( SR.CurrentDelegateSet )); } currentDelegateSet = true; } currentDelegate = value; } } [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] static public Enlistment Reenlist( Guid resourceManagerIdentifier, byte[] recoveryInformation, IEnlistmentNotification enlistmentNotification ) { if( resourceManagerIdentifier == Guid.Empty ) { throw new ArgumentException( SR.GetString( SR.BadResourceManagerId ), "resourceManagerIdentifier" ); } if ( null == recoveryInformation ) { throw new ArgumentNullException( "recoveryInformation" ); } if ( null == enlistmentNotification ) { throw new ArgumentNullException( "enlistmentNotification" ); } if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.Reenlist" ); } if ( DiagnosticTrace.Information ) { ReenlistTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), resourceManagerIdentifier ); } // Put the recovery information into a stream. MemoryStream stream = new MemoryStream( recoveryInformation ); int recoveryInformationVersion = 0; string nodeName = null; byte [] resourceManagerRecoveryInformation = null; try { BinaryReader reader = new BinaryReader( stream ); recoveryInformationVersion = reader.ReadInt32(); if( recoveryInformationVersion == TransactionManager.recoveryInformationVersion1 ) { nodeName = reader.ReadString(); resourceManagerRecoveryInformation = reader.ReadBytes( recoveryInformation.Length - checked ((int)stream.Position) ); } else { if ( DiagnosticTrace.Error ) { TransactionExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), SR.GetString( SR.UnrecognizedRecoveryInformation ) ); } throw new ArgumentException( SR.GetString( SR.UnrecognizedRecoveryInformation ), "recoveryInformation" ); } } catch( System.IO.EndOfStreamException e ) { if ( DiagnosticTrace.Error ) { TransactionExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), SR.GetString( SR.UnrecognizedRecoveryInformation ) ); } throw new ArgumentException( SR.GetString( SR.UnrecognizedRecoveryInformation ), "recoveryInformation", e); } catch( System.FormatException e ) { if ( DiagnosticTrace.Error ) { TransactionExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), SR.GetString( SR.UnrecognizedRecoveryInformation ) ); } throw new ArgumentException( SR.GetString( SR.UnrecognizedRecoveryInformation ), "recoveryInformation", e); } finally { stream.Close(); } Oletx.OletxTransactionManager transactionManager = CheckTransactionManager(nodeName); // Now ask the Transaction Manager to reenlist. object syncRoot = new object(); Enlistment returnValue = new Enlistment( enlistmentNotification, syncRoot ); EnlistmentState._EnlistmentStatePromoted.EnterState( returnValue.InternalEnlistment ); returnValue.InternalEnlistment.PromotedEnlistment = transactionManager.ReenlistTransaction( resourceManagerIdentifier, resourceManagerRecoveryInformation, (RecoveringInternalEnlistment)returnValue.InternalEnlistment ); if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.Reenlist" ); } return returnValue; } private static Oletx.OletxTransactionManager CheckTransactionManager(string nodeName) { Oletx.OletxTransactionManager tm = DistributedTransactionManager; if( !((tm.NodeName == null && (nodeName == null || nodeName.Length == 0)) || (tm.NodeName != null && tm.NodeName.Equals(nodeName))) ) { throw new ArgumentException( SR.GetString(SR.InvalidRecoveryInformation), "recoveryInformation" ); } return tm; } [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] static public void RecoveryComplete( Guid resourceManagerIdentifier ) { if( resourceManagerIdentifier == Guid.Empty ) { throw new ArgumentException( SR.GetString( SR.BadResourceManagerId ), "resourceManagerIdentifier" ); } if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.RecoveryComplete" ); } if ( DiagnosticTrace.Information ) { RecoveryCompleteTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), resourceManagerIdentifier ); } DistributedTransactionManager.ResourceManagerRecoveryComplete( resourceManagerIdentifier ); if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.RecoveryComplete" ); } } // Object for synchronizing access to the entire class( avoiding lock( typeof( ... )) ) private static object classSyncObject; // Helper object for static synchronization static object ClassSyncObject { get { if( classSyncObject == null ) { object o = new object(); Interlocked.CompareExchange( ref classSyncObject, o, null ); } return classSyncObject; } } internal static System.Transactions.IsolationLevel DefaultIsolationLevel { get { if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultIsolationLevel" ); MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultIsolationLevel" ); } return IsolationLevel.Serializable; } } static DefaultSettingsSection defaultSettings; static DefaultSettingsSection DefaultSettings { get { if( defaultSettings == null ) { defaultSettings = DefaultSettingsSection.GetSection(); } return defaultSettings; } } static MachineSettingsSection machineSettings; static MachineSettingsSection MachineSettings { get { if( machineSettings == null ) { machineSettings = MachineSettingsSection.GetSection(); } return machineSettings; } } private static bool _defaultTimeoutValidated; private static TimeSpan _defaultTimeout; public static TimeSpan DefaultTimeout { get { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultTimeout" ); } if( !_defaultTimeoutValidated ) { _defaultTimeout = ValidateTimeout( DefaultSettings.Timeout ); // If the timeout value got adjusted, it must have been greater than MaximumTimeout. if ( _defaultTimeout != DefaultSettings.Timeout ) { if ( DiagnosticTrace.Warning ) { ConfiguredDefaultTimeoutAdjustedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ) ); } } _defaultTimeoutValidated = true; } if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultTimeout" ); } return _defaultTimeout; } } private static bool _cachedMaxTimeout; private static TimeSpan _maximumTimeout; public static TimeSpan MaximumTimeout { get { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); if( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultMaximumTimeout" ); } if( !_cachedMaxTimeout ) { lock( ClassSyncObject ) { if( !_cachedMaxTimeout ) { TimeSpan temp = MachineSettings.MaxTimeout; Thread.MemoryBarrier(); _maximumTimeout = temp; _cachedMaxTimeout = true; } } } if( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultMaximumTimeout" ); } return _maximumTimeout; } } // This routine writes the "header" for the recovery information, based on the // type of the calling object and its provided parameter collection. This information // we be read back by the static Reenlist method to create the necessary transaction // manager object with the right parameters in order to do a ReenlistTransaction call. internal static byte[] GetRecoveryInformation( string startupInfo, byte[] resourceManagerRecoveryInformation ) { if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.GetRecoveryInformation" ); } MemoryStream stream = new MemoryStream(); byte[] returnValue = null; try { // Manually write the recovery information BinaryWriter writer = new BinaryWriter( stream ); writer.Write( TransactionManager.currentRecoveryVersion ); if( startupInfo != null ) { writer.Write( startupInfo ); } else { writer.Write( "" ); } writer.Write( resourceManagerRecoveryInformation ); writer.Flush(); returnValue = stream.ToArray(); } finally { stream.Close(); } if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.GetRecoveryInformation" ); } return returnValue; } internal static byte[] ConvertToByteArray( object thingToConvert ) { MemoryStream streamToWrite = new MemoryStream(); byte[] returnValue = null; try { // First seralize the type to the stream. IFormatter formatter = new BinaryFormatter(); formatter.Serialize( streamToWrite, thingToConvert ); returnValue = new byte[ streamToWrite.Length ]; streamToWrite.Position = 0; streamToWrite.Read( returnValue, 0, Convert.ToInt32( streamToWrite.Length, CultureInfo.InvariantCulture ) ); } finally { streamToWrite.Close(); } return returnValue; } ////// This static function throws an ArgumentOutOfRange if the specified IsolationLevel is not within /// the range of valid values. /// /// /// The IsolationLevel value to validate. /// internal static void ValidateIsolationLevel( IsolationLevel transactionIsolationLevel ) { switch ( transactionIsolationLevel ) { case IsolationLevel.Serializable: case IsolationLevel.RepeatableRead: case IsolationLevel.ReadCommitted: case IsolationLevel.ReadUncommitted: case IsolationLevel.Unspecified: case IsolationLevel.Chaos: case IsolationLevel.Snapshot: break; default: { throw new ArgumentOutOfRangeException( "transactionIsolationLevel" ); } } } ////// This static function throws an ArgumentOutOfRange if the specified TimeSpan does not meet /// requirements of a valid transaction timeout. Timeout values must be positive. /// /// /// The TimeSpan value to validate. /// internal static TimeSpan ValidateTimeout( TimeSpan transactionTimeout ) { if ( transactionTimeout < TimeSpan.Zero ) { throw new ArgumentOutOfRangeException( "transactionTimeout" ); } if ( TransactionManager.MaximumTimeout != TimeSpan.Zero ) { if ( transactionTimeout > TransactionManager.MaximumTimeout || transactionTimeout == TimeSpan.Zero ) { return TransactionManager.MaximumTimeout; } } return transactionTimeout; } internal static Transaction FindPromotedTransaction( Guid transactionIdentifier ) { Hashtable promotedTransactionTable = PromotedTransactionTable; WeakReference weakRef = (WeakReference) promotedTransactionTable[ transactionIdentifier ]; if ( null != weakRef ) { Transaction tx = weakRef.Target as Transaction; if ( null != tx ) { return tx.InternalClone(); } else // an old, moldy weak reference. Let's get rid of it. { lock( promotedTransactionTable ) { promotedTransactionTable.Remove( transactionIdentifier ); } } } return null; } internal static Transaction FindOrCreatePromotedTransaction( Guid transactionIdentifier, Oletx.OletxTransaction oletx ) { Transaction tx = null; Hashtable promotedTransactionTable = PromotedTransactionTable; lock(promotedTransactionTable) { WeakReference weakRef = (WeakReference) promotedTransactionTable[ transactionIdentifier ]; if ( null != weakRef ) { tx = weakRef.Target as Transaction; if ( null != tx ) { // If we found a transaction then dispose the oletx oletx.Dispose(); return tx.InternalClone(); } else // an old, moldy weak reference. Let's get rid of it. { lock( promotedTransactionTable ) { promotedTransactionTable.Remove( transactionIdentifier ); } } } tx = new Transaction( oletx ); // Since we are adding this reference to the table create an object that will clean that // entry up. tx.internalTransaction.finalizedObject = new FinalizedObject( tx.internalTransaction, oletx.Identifier ); weakRef = new WeakReference( tx, false ); promotedTransactionTable[ oletx.Identifier ] = weakRef; } oletx.savedLtmPromotedTransaction = tx; TransactionManager.FireDistributedTransactionStarted( tx ); return tx; } // Table for promoted transactions internal static Hashtable PromotedTransactionTable { get { if( promotedTransactionTable == null ) { lock( ClassSyncObject ) { if( promotedTransactionTable == null ) { Hashtable temp = new Hashtable( 100 ); Thread.MemoryBarrier(); promotedTransactionTable = temp; } } } return promotedTransactionTable; } } // Table for transaction timeouts internal static TransactionTable TransactionTable { get { if( transactionTable == null ) { lock( ClassSyncObject ) { if( transactionTable == null ) { TransactionTable temp = new TransactionTable(); Thread.MemoryBarrier(); transactionTable = temp; } } } return transactionTable; } } // Fault in a DistributedTransactionManager if one has not already been created. internal static Oletx.OletxTransactionManager distributedTransactionManager; internal static Oletx.OletxTransactionManager DistributedTransactionManager { get { // If the distributed transaction manager is not configured, throw an exception if( distributedTransactionManager == null ) { lock( ClassSyncObject ) { if( distributedTransactionManager == null ) { Oletx.OletxTransactionManager temp = new Oletx.OletxTransactionManager( DefaultSettings.DistributedTransactionManagerName); Thread.MemoryBarrier(); distributedTransactionManager = temp; } } } return distributedTransactionManager; } } internal static void ValidatePlatform() { if ( PlatformID.Win32NT != Environment.OSVersion.Platform ) { throw new PlatformNotSupportedException( SR.GetString( SR.OnlySupportedOnWinNT ) ); } // Note that this is purposly not synchronized because who cares if there is a ---- to set it. _platformValidated = true; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Configuration; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Security; using System.Security.Permissions; using System.Threading; using System.Transactions.Configuration; using System.Transactions.Diagnostics; using System.Xml; using System.Xml.Serialization; [assembly:BestFitMapping(false)] #pragma warning disable 618 [assembly:SecurityPermissionAttribute(SecurityAction.RequestMinimum)] #pragma warning restore 618 // No external data is ever passed to PrivilegedConfigurationManager.GetSection [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Scope="member", Target="System.Configuration.PrivilegedConfigurationManager.GetSection(System.String):System.Object")] namespace System.Transactions { public delegate Transaction HostCurrentTransactionCallback(); public delegate void TransactionStartedEventHandler(object sender, TransactionEventArgs e); public static class TransactionManager { // Revovery Information Version private const Int32 recoveryInformationVersion1 = 1; private const Int32 currentRecoveryVersion = recoveryInformationVersion1; // Record if the platform has been validated. internal static bool _platformValidated; // Hashtable of promoted transactions, keyed by identifier guid. This is used by // FindPromotedTransaction to support transaction equivalence when a transaction is // serialized and then deserialized back in this app-domain. private static Hashtable promotedTransactionTable; // Sorted Table of transaction timeouts private static TransactionTable transactionTable; private static TransactionStartedEventHandler distributedTransactionStartedDelegate; public static event TransactionStartedEventHandler DistributedTransactionStarted { [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] add { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); lock( ClassSyncObject ) { TransactionManager.distributedTransactionStartedDelegate = (TransactionStartedEventHandler)System.Delegate.Combine(TransactionManager.distributedTransactionStartedDelegate, value); if( value != null ) { ProcessExistingTransactions( value ); } } } [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] remove { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); lock ( ClassSyncObject ) { TransactionManager.distributedTransactionStartedDelegate = (TransactionStartedEventHandler)System.Delegate.Remove (TransactionManager.distributedTransactionStartedDelegate, value); } } } internal static void ProcessExistingTransactions( TransactionStartedEventHandler eventHandler ) { lock( PromotedTransactionTable ) { foreach( DictionaryEntry entry in PromotedTransactionTable ) { WeakReference weakRef = (WeakReference)entry.Value; Transaction tx = (Transaction)weakRef.Target; if( tx != null ) { TransactionEventArgs args = new TransactionEventArgs(); args.transaction = tx.InternalClone(); eventHandler( args.transaction, args ); } } } } internal static void FireDistributedTransactionStarted( Transaction transaction ) { TransactionStartedEventHandler localStartedEventHandler = null; lock( ClassSyncObject ) { localStartedEventHandler = TransactionManager.distributedTransactionStartedDelegate; } if ( null != localStartedEventHandler ) { TransactionEventArgs args = new TransactionEventArgs(); args.transaction = transaction.InternalClone(); localStartedEventHandler(args.transaction, args); } } // Data storage for current delegate internal static HostCurrentTransactionCallback currentDelegate = null; internal static bool currentDelegateSet = false; // CurrentDelegate // // Store a delegate to be used to query for an external current transaction. public static HostCurrentTransactionCallback HostCurrentCallback { // get_HostCurrentCallback is used from get_CurrentTransaction, which doesn't have any permission requirements. // We don't expose what is returned from this property in that case. But we don't want just anybody being able // to retrieve the value. [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] get { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); // Note do not add trace notifications to this method. It is called // at the startup of SQLCLR and tracing has too much working set overhead. return currentDelegate; } [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] set { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); // Note do not add trace notifications to this method. It is called // at the startup of SQLCLR and tracing has too much working set overhead. if( value == null ) { throw new ArgumentNullException( "value" ); } lock( ClassSyncObject ) { if( currentDelegateSet ) { throw new InvalidOperationException( SR.GetString( SR.CurrentDelegateSet )); } currentDelegateSet = true; } currentDelegate = value; } } [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] static public Enlistment Reenlist( Guid resourceManagerIdentifier, byte[] recoveryInformation, IEnlistmentNotification enlistmentNotification ) { if( resourceManagerIdentifier == Guid.Empty ) { throw new ArgumentException( SR.GetString( SR.BadResourceManagerId ), "resourceManagerIdentifier" ); } if ( null == recoveryInformation ) { throw new ArgumentNullException( "recoveryInformation" ); } if ( null == enlistmentNotification ) { throw new ArgumentNullException( "enlistmentNotification" ); } if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.Reenlist" ); } if ( DiagnosticTrace.Information ) { ReenlistTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), resourceManagerIdentifier ); } // Put the recovery information into a stream. MemoryStream stream = new MemoryStream( recoveryInformation ); int recoveryInformationVersion = 0; string nodeName = null; byte [] resourceManagerRecoveryInformation = null; try { BinaryReader reader = new BinaryReader( stream ); recoveryInformationVersion = reader.ReadInt32(); if( recoveryInformationVersion == TransactionManager.recoveryInformationVersion1 ) { nodeName = reader.ReadString(); resourceManagerRecoveryInformation = reader.ReadBytes( recoveryInformation.Length - checked ((int)stream.Position) ); } else { if ( DiagnosticTrace.Error ) { TransactionExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), SR.GetString( SR.UnrecognizedRecoveryInformation ) ); } throw new ArgumentException( SR.GetString( SR.UnrecognizedRecoveryInformation ), "recoveryInformation" ); } } catch( System.IO.EndOfStreamException e ) { if ( DiagnosticTrace.Error ) { TransactionExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), SR.GetString( SR.UnrecognizedRecoveryInformation ) ); } throw new ArgumentException( SR.GetString( SR.UnrecognizedRecoveryInformation ), "recoveryInformation", e); } catch( System.FormatException e ) { if ( DiagnosticTrace.Error ) { TransactionExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), SR.GetString( SR.UnrecognizedRecoveryInformation ) ); } throw new ArgumentException( SR.GetString( SR.UnrecognizedRecoveryInformation ), "recoveryInformation", e); } finally { stream.Close(); } Oletx.OletxTransactionManager transactionManager = CheckTransactionManager(nodeName); // Now ask the Transaction Manager to reenlist. object syncRoot = new object(); Enlistment returnValue = new Enlistment( enlistmentNotification, syncRoot ); EnlistmentState._EnlistmentStatePromoted.EnterState( returnValue.InternalEnlistment ); returnValue.InternalEnlistment.PromotedEnlistment = transactionManager.ReenlistTransaction( resourceManagerIdentifier, resourceManagerRecoveryInformation, (RecoveringInternalEnlistment)returnValue.InternalEnlistment ); if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.Reenlist" ); } return returnValue; } private static Oletx.OletxTransactionManager CheckTransactionManager(string nodeName) { Oletx.OletxTransactionManager tm = DistributedTransactionManager; if( !((tm.NodeName == null && (nodeName == null || nodeName.Length == 0)) || (tm.NodeName != null && tm.NodeName.Equals(nodeName))) ) { throw new ArgumentException( SR.GetString(SR.InvalidRecoveryInformation), "recoveryInformation" ); } return tm; } [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] static public void RecoveryComplete( Guid resourceManagerIdentifier ) { if( resourceManagerIdentifier == Guid.Empty ) { throw new ArgumentException( SR.GetString( SR.BadResourceManagerId ), "resourceManagerIdentifier" ); } if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.RecoveryComplete" ); } if ( DiagnosticTrace.Information ) { RecoveryCompleteTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), resourceManagerIdentifier ); } DistributedTransactionManager.ResourceManagerRecoveryComplete( resourceManagerIdentifier ); if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.RecoveryComplete" ); } } // Object for synchronizing access to the entire class( avoiding lock( typeof( ... )) ) private static object classSyncObject; // Helper object for static synchronization static object ClassSyncObject { get { if( classSyncObject == null ) { object o = new object(); Interlocked.CompareExchange( ref classSyncObject, o, null ); } return classSyncObject; } } internal static System.Transactions.IsolationLevel DefaultIsolationLevel { get { if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultIsolationLevel" ); MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultIsolationLevel" ); } return IsolationLevel.Serializable; } } static DefaultSettingsSection defaultSettings; static DefaultSettingsSection DefaultSettings { get { if( defaultSettings == null ) { defaultSettings = DefaultSettingsSection.GetSection(); } return defaultSettings; } } static MachineSettingsSection machineSettings; static MachineSettingsSection MachineSettings { get { if( machineSettings == null ) { machineSettings = MachineSettingsSection.GetSection(); } return machineSettings; } } private static bool _defaultTimeoutValidated; private static TimeSpan _defaultTimeout; public static TimeSpan DefaultTimeout { get { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultTimeout" ); } if( !_defaultTimeoutValidated ) { _defaultTimeout = ValidateTimeout( DefaultSettings.Timeout ); // If the timeout value got adjusted, it must have been greater than MaximumTimeout. if ( _defaultTimeout != DefaultSettings.Timeout ) { if ( DiagnosticTrace.Warning ) { ConfiguredDefaultTimeoutAdjustedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ) ); } } _defaultTimeoutValidated = true; } if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultTimeout" ); } return _defaultTimeout; } } private static bool _cachedMaxTimeout; private static TimeSpan _maximumTimeout; public static TimeSpan MaximumTimeout { get { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); if( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultMaximumTimeout" ); } if( !_cachedMaxTimeout ) { lock( ClassSyncObject ) { if( !_cachedMaxTimeout ) { TimeSpan temp = MachineSettings.MaxTimeout; Thread.MemoryBarrier(); _maximumTimeout = temp; _cachedMaxTimeout = true; } } } if( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.get_DefaultMaximumTimeout" ); } return _maximumTimeout; } } // This routine writes the "header" for the recovery information, based on the // type of the calling object and its provided parameter collection. This information // we be read back by the static Reenlist method to create the necessary transaction // manager object with the right parameters in order to do a ReenlistTransaction call. internal static byte[] GetRecoveryInformation( string startupInfo, byte[] resourceManagerRecoveryInformation ) { if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.GetRecoveryInformation" ); } MemoryStream stream = new MemoryStream(); byte[] returnValue = null; try { // Manually write the recovery information BinaryWriter writer = new BinaryWriter( stream ); writer.Write( TransactionManager.currentRecoveryVersion ); if( startupInfo != null ) { writer.Write( startupInfo ); } else { writer.Write( "" ); } writer.Write( resourceManagerRecoveryInformation ); writer.Flush(); returnValue = stream.ToArray(); } finally { stream.Close(); } if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceBase ), "TransactionManager.GetRecoveryInformation" ); } return returnValue; } internal static byte[] ConvertToByteArray( object thingToConvert ) { MemoryStream streamToWrite = new MemoryStream(); byte[] returnValue = null; try { // First seralize the type to the stream. IFormatter formatter = new BinaryFormatter(); formatter.Serialize( streamToWrite, thingToConvert ); returnValue = new byte[ streamToWrite.Length ]; streamToWrite.Position = 0; streamToWrite.Read( returnValue, 0, Convert.ToInt32( streamToWrite.Length, CultureInfo.InvariantCulture ) ); } finally { streamToWrite.Close(); } return returnValue; } ////// This static function throws an ArgumentOutOfRange if the specified IsolationLevel is not within /// the range of valid values. /// /// /// The IsolationLevel value to validate. /// internal static void ValidateIsolationLevel( IsolationLevel transactionIsolationLevel ) { switch ( transactionIsolationLevel ) { case IsolationLevel.Serializable: case IsolationLevel.RepeatableRead: case IsolationLevel.ReadCommitted: case IsolationLevel.ReadUncommitted: case IsolationLevel.Unspecified: case IsolationLevel.Chaos: case IsolationLevel.Snapshot: break; default: { throw new ArgumentOutOfRangeException( "transactionIsolationLevel" ); } } } ////// This static function throws an ArgumentOutOfRange if the specified TimeSpan does not meet /// requirements of a valid transaction timeout. Timeout values must be positive. /// /// /// The TimeSpan value to validate. /// internal static TimeSpan ValidateTimeout( TimeSpan transactionTimeout ) { if ( transactionTimeout < TimeSpan.Zero ) { throw new ArgumentOutOfRangeException( "transactionTimeout" ); } if ( TransactionManager.MaximumTimeout != TimeSpan.Zero ) { if ( transactionTimeout > TransactionManager.MaximumTimeout || transactionTimeout == TimeSpan.Zero ) { return TransactionManager.MaximumTimeout; } } return transactionTimeout; } internal static Transaction FindPromotedTransaction( Guid transactionIdentifier ) { Hashtable promotedTransactionTable = PromotedTransactionTable; WeakReference weakRef = (WeakReference) promotedTransactionTable[ transactionIdentifier ]; if ( null != weakRef ) { Transaction tx = weakRef.Target as Transaction; if ( null != tx ) { return tx.InternalClone(); } else // an old, moldy weak reference. Let's get rid of it. { lock( promotedTransactionTable ) { promotedTransactionTable.Remove( transactionIdentifier ); } } } return null; } internal static Transaction FindOrCreatePromotedTransaction( Guid transactionIdentifier, Oletx.OletxTransaction oletx ) { Transaction tx = null; Hashtable promotedTransactionTable = PromotedTransactionTable; lock(promotedTransactionTable) { WeakReference weakRef = (WeakReference) promotedTransactionTable[ transactionIdentifier ]; if ( null != weakRef ) { tx = weakRef.Target as Transaction; if ( null != tx ) { // If we found a transaction then dispose the oletx oletx.Dispose(); return tx.InternalClone(); } else // an old, moldy weak reference. Let's get rid of it. { lock( promotedTransactionTable ) { promotedTransactionTable.Remove( transactionIdentifier ); } } } tx = new Transaction( oletx ); // Since we are adding this reference to the table create an object that will clean that // entry up. tx.internalTransaction.finalizedObject = new FinalizedObject( tx.internalTransaction, oletx.Identifier ); weakRef = new WeakReference( tx, false ); promotedTransactionTable[ oletx.Identifier ] = weakRef; } oletx.savedLtmPromotedTransaction = tx; TransactionManager.FireDistributedTransactionStarted( tx ); return tx; } // Table for promoted transactions internal static Hashtable PromotedTransactionTable { get { if( promotedTransactionTable == null ) { lock( ClassSyncObject ) { if( promotedTransactionTable == null ) { Hashtable temp = new Hashtable( 100 ); Thread.MemoryBarrier(); promotedTransactionTable = temp; } } } return promotedTransactionTable; } } // Table for transaction timeouts internal static TransactionTable TransactionTable { get { if( transactionTable == null ) { lock( ClassSyncObject ) { if( transactionTable == null ) { TransactionTable temp = new TransactionTable(); Thread.MemoryBarrier(); transactionTable = temp; } } } return transactionTable; } } // Fault in a DistributedTransactionManager if one has not already been created. internal static Oletx.OletxTransactionManager distributedTransactionManager; internal static Oletx.OletxTransactionManager DistributedTransactionManager { get { // If the distributed transaction manager is not configured, throw an exception if( distributedTransactionManager == null ) { lock( ClassSyncObject ) { if( distributedTransactionManager == null ) { Oletx.OletxTransactionManager temp = new Oletx.OletxTransactionManager( DefaultSettings.DistributedTransactionManagerName); Thread.MemoryBarrier(); distributedTransactionManager = temp; } } } return distributedTransactionManager; } } internal static void ValidatePlatform() { if ( PlatformID.Win32NT != Environment.OSVersion.Platform ) { throw new PlatformNotSupportedException( SR.GetString( SR.OnlySupportedOnWinNT ) ); } // Note that this is purposly not synchronized because who cares if there is a ---- to set it. _platformValidated = true; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RegularExpressionValidator.cs
- Literal.cs
- ColumnMapProcessor.cs
- DbXmlEnabledProviderManifest.cs
- ModuleConfigurationInfo.cs
- ApplicationSecurityInfo.cs
- TextEffect.cs
- EditorPartChrome.cs
- MimePart.cs
- IgnoreDataMemberAttribute.cs
- OleDbEnumerator.cs
- DeobfuscatingStream.cs
- DataBoundControlHelper.cs
- FunctionOverloadResolver.cs
- ContextMarshalException.cs
- CharAnimationBase.cs
- StorageEndPropertyMapping.cs
- PlainXmlSerializer.cs
- RemoteCryptoRsaServiceProvider.cs
- DefaultPrintController.cs
- WebProxyScriptElement.cs
- ValidatorCollection.cs
- PaperSize.cs
- ADMembershipUser.cs
- DPCustomTypeDescriptor.cs
- TypeUtil.cs
- ConnectionInterfaceCollection.cs
- InputBinding.cs
- UncommonField.cs
- FileIOPermission.cs
- SqlUserDefinedTypeAttribute.cs
- CopyAction.cs
- ToolStripContainer.cs
- ObjectDataSourceEventArgs.cs
- ExpandCollapseProviderWrapper.cs
- Error.cs
- ObjectAnimationUsingKeyFrames.cs
- SpellerError.cs
- WorkflowServiceHostFactory.cs
- AudioBase.cs
- WaitForChangedResult.cs
- ProfileSettings.cs
- FileVersion.cs
- ReferenceSchema.cs
- XamlSerializer.cs
- PriorityBinding.cs
- FileUtil.cs
- ConditionBrowserDialog.cs
- XsltFunctions.cs
- EFDataModelProvider.cs
- InvalidPropValue.cs
- StrongTypingException.cs
- ScriptingScriptResourceHandlerSection.cs
- SmiRequestExecutor.cs
- WebPartsSection.cs
- InkCanvasInnerCanvas.cs
- StrongNameMembershipCondition.cs
- SiteMembershipCondition.cs
- SecurityUtils.cs
- CacheEntry.cs
- HMACRIPEMD160.cs
- XmlSecureResolver.cs
- TemplateBindingExtensionConverter.cs
- XmlSchemaCompilationSettings.cs
- ISAPIWorkerRequest.cs
- UserControl.cs
- RedistVersionInfo.cs
- RemoveStoryboard.cs
- SoapAttributes.cs
- MultiSelector.cs
- LineGeometry.cs
- PaintEvent.cs
- EntityTransaction.cs
- RewritingPass.cs
- HandlerMappingMemo.cs
- rsa.cs
- ListSortDescription.cs
- TextAnchor.cs
- CompositeDataBoundControl.cs
- StringResourceManager.cs
- SignatureHelper.cs
- OdbcRowUpdatingEvent.cs
- StatusBarItemAutomationPeer.cs
- StringCollection.cs
- ToolStripStatusLabel.cs
- HTTPNotFoundHandler.cs
- C14NUtil.cs
- GeometryValueSerializer.cs
- DependencyObjectPropertyDescriptor.cs
- PrefixQName.cs
- DataGridViewColumn.cs
- BitmapEffectDrawing.cs
- Path.cs
- SHA256CryptoServiceProvider.cs
- DebugView.cs
- GlobalProxySelection.cs
- StringTraceRecord.cs
- InvalidateEvent.cs
- MouseEventArgs.cs
- EncryptedKey.cs