Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / tx / System / Transactions / InternalTransaction.cs / 1305376 / InternalTransaction.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Transactions { using System; using System.Collections; using System.Diagnostics; using System.Globalization; using System.Runtime.Serialization; using System.Threading; using System.Transactions.Diagnostics; // InternalTransaction // // This class holds the state and all data common to a transaction instance class InternalTransaction : IDisposable { // This variable manages the state of the transaction it should be one of the // static elements of TransactionState derived from TransactionState. protected TransactionState transactionState; internal TransactionState State { get { return transactionState; } set { transactionState = value; } } // This variable holds the state that the transaction will promote to. By // default it uses the straight forward TransactionStatePromoted. If the // transaction has a promotable single phase enlistment however it must use // a different state so that it is promoted correctly. internal TransactionState promoteState; #if DEBUG // Keep a history of th transaction states internal const int MaxStateHist = 20; internal TransactionState[] stateHistory = new TransactionState [MaxStateHist]; internal int currentStateHist; #endif // Finalized object see class definition for the use of this object internal FinalizedObject finalizedObject; internal int transactionHash; internal int TransactionHash { get { return this.transactionHash; } } internal static int nextHash; // timeout stores a relative timeout for the transaction. absoluteTimeout stores // the actual time in ticks. private long absoluteTimeout; internal long AbsoluteTimeout { get { return this.absoluteTimeout; } } // record the current number of ticks active when the transaction is created. private Int64 creationTime; internal Int64 CreationTime { get { return this.creationTime; } set { this.creationTime = value; } } // The goal for the LTM is to only allocate as few heap objects as possible for a given // transaction and all of its enlistments. To accomplish this, enlistment objects are // held in system arrays. The transaction contains one enlistment for the single durable // enlistment it can handle and a small array of volatile enlistments. If the number of // enlistments for a given transaction exceeds the capacity of the current array a new // larger array will be created and the contents of the old array will be copied into it. // Heuristic data based on TransactionType can be created to avoid this sort of copy // operation repeatedly for a given type of transaction. So if a transaction of a specific // type continually causes the array size to be increased the LTM could start // allocating a larger array initially for transactions of that type. internal InternalEnlistment durableEnlistment; internal VolatileEnlistmentSet phase0Volatiles; internal VolatileEnlistmentSet phase1Volatiles; // This member stores the number of phase 0 volatiles for the last wave internal int phase0VolatileWaveCount; // These members are used for promoted waves of dependent blocking clones. The Ltm // does not register individually for each blocking clone created in phase 0. Instead // it multiplexes a single phase 0 blocking clone only created after phase 0 has started. internal Oletx.OletxDependentTransaction phase0WaveDependentClone; internal int phase0WaveDependentCloneCount; // These members are used for keeping track of aborting dependent clones if we promote // BEFORE we get an aborting dependent clone or a Ph1 volatile enlistment. If we // promote before we get either of these, then we never create a Ph1 volatile enlistment // on the distributed TM. If we promote AFTER an aborting dependent clone or Ph1 volatile // enlistment is created, then we create a Ph1 volatile enlistment on the distributed TM // as part of promotion, so these won't be used. In that case, the Ph1 volatile enlistment // on the distributed TM takes care of checking to make sure all the aborting dependent // clones have completed as part of its Prepare processing. These are used in conjunction with // phase1volatiles.dependentclones. internal Oletx.OletxDependentTransaction abortingDependentClone; internal int abortingDependentCloneCount; // When the size of the volatile enlistment array grows increase it by this amount. internal const int volatileArrayIncrement = 8; // Data maintained for TransactionTable participation internal Bucket tableBucket; internal int bucketIndex; // Delegate to fire on transaction completion internal TransactionCompletedEventHandler transactionCompletedDelegate; // If this transaction get's promoted keep a reference to the promoted transaction private Oletx.OletxTransaction promotedTransaction; internal Oletx.OletxTransaction PromotedTransaction { get { return this.promotedTransaction; } set { Debug.Assert( this.promotedTransaction == null, "A transaction can only be promoted once!" ); this.promotedTransaction = value; } } // If there was an exception that happened during promotion save that exception so that it // can be used as an inner exception to the transaciton aborted exception. internal Exception innerException = null; // Note the number of Transaction objects supported by this object internal int cloneCount; // The number of enlistments on this transaction. internal int enlistmentCount = 0; // Manual Reset event for IAsyncResult support internal ManualResetEvent asyncResultEvent; // Store the callback and state for the caller of BeginCommit internal bool asyncCommit; internal AsyncCallback asyncCallback; internal object asyncState; // Flag to indicate if we need to be pulsed for tx completion internal bool needPulse; // Store the transaction information object internal TransactionInformation transactionInformation; // Store a reference to the owning Committable Transaction internal CommittableTransaction committableTransaction; // Store a reference to the outcome source internal Transaction outcomeSource; // Object for synchronizing access to the entire class( avoiding lock( typeof( ... )) ) private static object classSyncObject; internal static object ClassSyncObject { get { if( classSyncObject == null ) { object o = new object(); Interlocked.CompareExchange( ref classSyncObject, o, null ); } return classSyncObject; } } static string instanceIdentifier; static internal string InstanceIdentifier { get { if( instanceIdentifier == null ) { lock( ClassSyncObject ) { if( instanceIdentifier == null ) { string temp = Guid.NewGuid().ToString() + ":"; Thread.MemoryBarrier(); instanceIdentifier = temp; } } } return instanceIdentifier; } } // The trace identifier for the internal transaction. private TransactionTraceIdentifier traceIdentifier; internal TransactionTraceIdentifier TransactionTraceId { get { if( this.traceIdentifier == TransactionTraceIdentifier.Empty ) { lock( this ) { if( this.traceIdentifier == TransactionTraceIdentifier.Empty ) { TransactionTraceIdentifier temp = new TransactionTraceIdentifier( InstanceIdentifier + Convert.ToString( this.transactionHash, CultureInfo.InvariantCulture ), 0 ); Thread.MemoryBarrier(); this.traceIdentifier = temp; } } } return this.traceIdentifier; } } internal ITransactionPromoter promoter; // Construct an internal transaction internal InternalTransaction( TimeSpan timeout, CommittableTransaction committableTransaction ) { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); // Calculate the absolute timeout for this transaction this.absoluteTimeout = TransactionManager.TransactionTable.TimeoutTicks( timeout ); // Start the transaction off as active TransactionState._TransactionStateActive.EnterState( this ); // Until otherwise noted this transaction uses normal promotion. this.promoteState = TransactionState._TransactionStatePromoted; // Keep a reference to the commitable transaction this.committableTransaction = committableTransaction; this.outcomeSource = committableTransaction; // Initialize the hash this.transactionHash = TransactionManager.TransactionTable.Add( this ); } // Construct an internal transaction internal InternalTransaction( Transaction outcomeSource, Oletx.OletxTransaction distributedTx ) { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); this.promotedTransaction = distributedTx; this.absoluteTimeout = long.MaxValue; // Store the initial creater as it will be the source of outcome events this.outcomeSource = outcomeSource; // Initialize the hash this.transactionHash = TransactionManager.TransactionTable.Add( this ); // Start the transaction off as active TransactionState._TransactionStateNonCommittablePromoted.EnterState( this ); // Until otherwise noted this transaction uses normal promotion. this.promoteState = TransactionState._TransactionStateNonCommittablePromoted; } // Construct an internal transaction internal InternalTransaction( Transaction outcomeSource, ITransactionPromoter promoter ) { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); this.absoluteTimeout = long.MaxValue; // Store the initial creater as it will be the source of outcome events this.outcomeSource = outcomeSource; // Initialize the hash this.transactionHash = TransactionManager.TransactionTable.Add( this ); // Save the transaction promoter. this.promoter = promoter; // This transaction starts in a special state. TransactionState._TransactionStateSubordinateActive.EnterState( this ); // This transaction promotes through delegation this.promoteState = TransactionState._TransactionStateDelegatedSubordinate; } internal static void DistributedTransactionOutcome( InternalTransaction tx, TransactionStatus status ) { FinalizedObject fo = null; lock( tx ) { if ( null == tx.innerException ) { tx.innerException = tx.PromotedTransaction.InnerException; } switch (status) { case TransactionStatus.Committed : { tx.State.ChangeStatePromotedCommitted( tx ); break; } case TransactionStatus.Aborted : { tx.State.ChangeStatePromotedAborted( tx ); break; } case TransactionStatus.InDoubt : { tx.State.InDoubtFromDtc( tx ); break; } default : { Debug.Assert( false, "InternalTransaction.DistributedTransactionOutcome - Unexpected TransactionStatus" ); TransactionException.CreateInvalidOperationException( SR.GetString( SR.TraceSourceLtm ), "", null ); break; } } fo = tx.finalizedObject; } if( null != fo ) { fo.Dispose(); } } #region Outcome Events // Signal Waiters anyone waiting for transaction outcome. internal void SignalAsyncCompletion() { if( this.asyncResultEvent != null ) { this.asyncResultEvent.Set(); } if( this.asyncCallback != null ) { System.Threading.Monitor.Exit( this ); // Don't hold a lock calling user code. try { this.asyncCallback( this.committableTransaction ); } finally { #pragma warning disable 0618 //@ System.Threading.Monitor.Enter(this); #pragma warning restore 0618 } } } // Fire completion to anyone registered for outcome internal void FireCompletion( ) { TransactionCompletedEventHandler eventHandlers = this.transactionCompletedDelegate; if( eventHandlers != null ) { TransactionEventArgs args = new TransactionEventArgs(); args.transaction = this.outcomeSource.InternalClone(); eventHandlers( args.transaction, args ); } } #endregion #region IDisposable Members // FXCop wants us to dispose nextLink, which is another InternalTransaction, and thus disposable. But we don't // want to do that here. That link is for the list of all InternalTransactions. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")] public void Dispose() { if( this.promotedTransaction != null ) { // If there is a promoted transaction dispose it. this.promotedTransaction.Dispose(); } } #endregion } // Finalized Object // // This object is created if the InternalTransaction needs some kind of finalization. An // InternalTransaction will only need finalization if it is promoted so having a finalizer // would only hurt performance for the unpromoted case. When the Ltm does promote it creates this // object which is finalized and will handle the necessary cleanup. sealed class FinalizedObject : IDisposable { // Keep the identifier separate. Since it is a struct it wont be finalized out from under // this object. Guid identifier; InternalTransaction internalTransaction; internal FinalizedObject( InternalTransaction internalTransaction, Guid identifier ) { this.internalTransaction = internalTransaction; this.identifier = identifier; } private void Dispose( bool disposing ) { if( disposing ) { GC.SuppressFinalize(this); } // We need to remove the entry for the transaction from the static // LightweightTransactionManager.PromotedTransactionTable. Hashtable promotedTransactionTable = TransactionManager.PromotedTransactionTable; lock( promotedTransactionTable ) { WeakReference weakRef = (WeakReference) promotedTransactionTable[ this.identifier ]; if ( null != weakRef ) { if( weakRef.Target != null ) { weakRef.Target = null; } } promotedTransactionTable.Remove( this.identifier ); } } public void Dispose() { Dispose(true); } ~FinalizedObject() { Dispose(false); } } } // 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
- WebZone.cs
- WebCategoryAttribute.cs
- DetailsViewUpdatedEventArgs.cs
- SynchronizationScope.cs
- DataTemplateSelector.cs
- SchemaEntity.cs
- Span.cs
- _LazyAsyncResult.cs
- OutputWindow.cs
- OleDbWrapper.cs
- HttpStreams.cs
- DebuggerAttributes.cs
- XmlChildNodes.cs
- SmiMetaDataProperty.cs
- ValidatingReaderNodeData.cs
- TextPointer.cs
- StdValidatorsAndConverters.cs
- ButtonFlatAdapter.cs
- SQLInt16Storage.cs
- BinHexEncoder.cs
- ProcessHostMapPath.cs
- BackgroundWorker.cs
- AtomicFile.cs
- DetailsView.cs
- OperationCanceledException.cs
- QilSortKey.cs
- CompoundFileStreamReference.cs
- COM2ExtendedBrowsingHandler.cs
- PropertyCollection.cs
- PagesChangedEventArgs.cs
- WeakReferenceEnumerator.cs
- CodeCatchClauseCollection.cs
- MessageSmuggler.cs
- SystemIcmpV4Statistics.cs
- exports.cs
- Psha1DerivedKeyGenerator.cs
- MulticastNotSupportedException.cs
- SettingsPropertyNotFoundException.cs
- SymmetricKeyWrap.cs
- BinaryFormatterWriter.cs
- DataFieldCollectionEditor.cs
- UnionCodeGroup.cs
- Label.cs
- WebChannelFactory.cs
- URLAttribute.cs
- SplineQuaternionKeyFrame.cs
- AlignmentYValidation.cs
- ServiceHandle.cs
- RootBrowserWindow.cs
- CodeAssignStatement.cs
- ChineseLunisolarCalendar.cs
- PathData.cs
- XpsManager.cs
- ValidatorCollection.cs
- SimpleHandlerBuildProvider.cs
- FrameDimension.cs
- AxHost.cs
- GestureRecognizer.cs
- VectorAnimationUsingKeyFrames.cs
- ADRoleFactoryConfiguration.cs
- CodeBlockBuilder.cs
- BaseTreeIterator.cs
- PagerSettings.cs
- ReadOnlyDictionary.cs
- StorageSetMapping.cs
- ProcessModule.cs
- Label.cs
- ScrollPattern.cs
- parserscommon.cs
- ClickablePoint.cs
- xamlnodes.cs
- Point.cs
- Rect3D.cs
- ScriptReferenceBase.cs
- LiteralControl.cs
- AncillaryOps.cs
- EncodingInfo.cs
- ServiceKnownTypeAttribute.cs
- EntityTypeEmitter.cs
- CuspData.cs
- Sql8ConformanceChecker.cs
- ToolStripDropDown.cs
- ResourceBinder.cs
- MetabaseSettings.cs
- ListViewUpdatedEventArgs.cs
- ElementsClipboardData.cs
- Visitor.cs
- PerspectiveCamera.cs
- ScrollChrome.cs
- Brush.cs
- arclist.cs
- PeerNameRecord.cs
- EditorZone.cs
- TargetConverter.cs
- Unit.cs
- CompilerErrorCollection.cs
- PatternMatcher.cs
- DataGridCell.cs
- SendKeys.cs
- SqlDuplicator.cs