Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DbgUtil.cs
- Bits.cs
- GridViewCellAutomationPeer.cs
- PropertyPathWorker.cs
- DataContractSerializerOperationBehavior.cs
- PrefixHandle.cs
- LoggedException.cs
- TextEditorMouse.cs
- SecureStringHasher.cs
- SurrogateSelector.cs
- EventSourceCreationData.cs
- FilteredAttributeCollection.cs
- TextHidden.cs
- TraceRecord.cs
- RemotingClientProxy.cs
- CustomLineCap.cs
- BitHelper.cs
- PlatformCulture.cs
- ParentControlDesigner.cs
- ProxyFragment.cs
- Wildcard.cs
- DrawingGroup.cs
- SqlSupersetValidator.cs
- EndPoint.cs
- ResetableIterator.cs
- WorkflowMarkupSerializationException.cs
- OracleFactory.cs
- BinaryMessageEncodingBindingElement.cs
- UniqueIdentifierService.cs
- DataGridViewMethods.cs
- Single.cs
- PerformanceCounter.cs
- AssemblyInfo.cs
- DeviceContexts.cs
- ListViewGroupItemCollection.cs
- MethodToken.cs
- FactoryGenerator.cs
- SettingsSavedEventArgs.cs
- SyndicationSerializer.cs
- Effect.cs
- FormViewPagerRow.cs
- Parameter.cs
- AsymmetricSignatureFormatter.cs
- MetadataPropertyAttribute.cs
- RuntimeConfigLKG.cs
- OracleFactory.cs
- BindingListCollectionView.cs
- DoWorkEventArgs.cs
- SuppressMergeCheckAttribute.cs
- QueryServiceConfigHandle.cs
- GroupAggregateExpr.cs
- IisTraceWebEventProvider.cs
- SmtpNegotiateAuthenticationModule.cs
- WorkflowServiceAttributes.cs
- SignedXml.cs
- CodeAttributeArgument.cs
- DSASignatureDeformatter.cs
- LoadGrammarCompletedEventArgs.cs
- HtmlSelect.cs
- DataGridViewCellValidatingEventArgs.cs
- DataServiceRequestException.cs
- PeerTransportCredentialType.cs
- RsaSecurityTokenAuthenticator.cs
- XmlSubtreeReader.cs
- VarRefManager.cs
- AspNetHostingPermission.cs
- SQLRoleProvider.cs
- ScriptServiceAttribute.cs
- Point.cs
- ViewBox.cs
- FtpWebResponse.cs
- SystemResourceKey.cs
- printdlgexmarshaler.cs
- SimpleApplicationHost.cs
- View.cs
- MatrixIndependentAnimationStorage.cs
- ParseHttpDate.cs
- Int64Storage.cs
- CompilationUnit.cs
- TraceUtils.cs
- DbDeleteCommandTree.cs
- MimeTypeAttribute.cs
- CodeArgumentReferenceExpression.cs
- XmlSchemaRedefine.cs
- DataControlLinkButton.cs
- PositiveTimeSpanValidatorAttribute.cs
- SamlAttributeStatement.cs
- SessionParameter.cs
- CompressStream.cs
- ContentFileHelper.cs
- DocumentReference.cs
- CompositionTarget.cs
- InvalidPipelineStoreException.cs
- CodeIdentifier.cs
- UnknownBitmapDecoder.cs
- CheckBoxBaseAdapter.cs
- DataSourceDesigner.cs
- Oid.cs
- ToolStripItemCollection.cs
- SimpleHandlerFactory.cs