// ........................................................................................................
 internal static void Complete(Transaction transaction, Exception error)
 {
     try
     {
         if (error == null)
         {
             CommittableTransaction commit = (transaction as CommittableTransaction);
             if (commit != null)
             {
                 commit.Commit();
             }
             else
             {
                 DependentTransaction complete = (transaction as DependentTransaction);
                 if (complete != null)
                 {
                     complete.Complete();
                 }
             }
         }
         else
         {
             transaction.Rollback();
         }
     }
     catch (TransactionException e)
     {
         DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true));
     }
 }
 internal static void Complete(Transaction transaction, Exception error)
 {
     try
     {
         if (error == null)
         {
             CommittableTransaction transaction2 = transaction as CommittableTransaction;
             if (transaction2 != null)
             {
                 transaction2.Commit();
             }
             else
             {
                 DependentTransaction transaction3 = transaction as DependentTransaction;
                 if (transaction3 != null)
                 {
                     transaction3.Complete();
                 }
             }
         }
         else
         {
             transaction.Rollback();
         }
     }
     catch (TransactionException exception)
     {
         DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error);
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(System.ServiceModel.SR.GetString("SFxTransactionAsyncAborted"), "TransactionAborted", true));
     }
 }
 internal TransactionScope CreateTransactionScope(Transaction transaction)
 {
     lock (this.mutex)
     {
         if (this.pending.ContainsKey(transaction))
         {
             try
             {
                 return(new TransactionScope(transaction));
             }
             catch (TransactionException exception)
             {
                 DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error);
             }
         }
     }
     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(System.ServiceModel.SR.GetString("SFxTransactionAsyncAborted"), "TransactionAborted", true));
 }
 internal void ThreadLeave()
 {
     if (this.scope != null)
     {
         if (!this.transactionSetComplete)
         {
             this.scope.Complete();
         }
         try
         {
             this.scope.Dispose();
         }
         catch (TransactionException exception)
         {
             DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error);
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(System.ServiceModel.SR.GetString("SFxTransactionAsyncAborted"), "TransactionAborted", true));
         }
     }
 }
        // ........................................................................................................
        internal TransactionScope CreateTransactionScope(Transaction transaction)
        {
            lock (this.mutex)
            {
                if (this.pending.ContainsKey(transaction))
                {
                    try
                    {
                        return(new TransactionScope(transaction));
                    }
                    catch (TransactionException e)
                    {
                        DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
                        //we'll rethrow below
                    }
                }
            }

            //the transaction was asynchronously aborted
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true));
        }
        internal void ThreadLeave()
        {
            if (this.scope != null)
            {
                if (!this.transactionSetComplete)
                {
                    this.scope.Complete();
                }

                try
                {
                    this.scope.Dispose();
                    this.scope = null;
                }
                catch (TransactionException e)
                {
                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true));
                }
            }
        }
 internal void CheckIfTxCompletedAndUpdateAttached(ref MessageRpc rpc, bool isConcurrent)
 {
     if (rpc.Transaction.Current != null)
     {
         lock (this.mutex)
         {
             if (!isConcurrent)
             {
                 if (this.shouldReleaseInstance)
                 {
                     this.shouldReleaseInstance = false;
                     if (rpc.Error == null)
                     {
                         rpc.Error = TransactionBehavior.CreateFault(System.ServiceModel.SR.GetString("SFxTransactionAsyncAborted"), "TransactionAborted", true);
                         DiagnosticUtility.ExceptionUtility.TraceHandledException(rpc.Error, TraceEventType.Error);
                         if (DiagnosticUtility.ShouldTraceInformation)
                         {
                             TraceUtility.TraceEvent(TraceEventType.Information, 0xe0009, System.ServiceModel.SR.GetString("TraceCodeTxCompletionStatusCompletedForAsyncAbort", new object[] { rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name }));
                         }
                     }
                 }
                 if (rpc.Transaction.IsCompleted || (rpc.Error != null))
                 {
                     if (DiagnosticUtility.ShouldTraceInformation)
                     {
                         if (rpc.Error != null)
                         {
                             TraceUtility.TraceEvent(TraceEventType.Information, 0xe0006, System.ServiceModel.SR.GetString("TraceCodeTxCompletionStatusCompletedForError", new object[] { rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name }));
                         }
                         else
                         {
                             TraceUtility.TraceEvent(TraceEventType.Information, 0xe0005, System.ServiceModel.SR.GetString("TraceCodeTxCompletionStatusCompletedForAutocomplete", new object[] { rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name }));
                         }
                     }
                     this.Attached = null;
                     if (this.waiting != null)
                     {
                         DiagnosticUtility.FailFast("waiting should be null when resetting current");
                     }
                     this.current = null;
                 }
                 else
                 {
                     this.Attached = rpc.Transaction.Current;
                     if (DiagnosticUtility.ShouldTraceInformation)
                     {
                         TraceUtility.TraceEvent(TraceEventType.Information, 0xe000a, System.ServiceModel.SR.GetString("TraceCodeTxCompletionStatusRemainsAttached", new object[] { rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name }));
                     }
                 }
             }
             else if (!this.pending.ContainsKey(rpc.Transaction.Current) && (rpc.Error == null))
             {
                 rpc.Error = TransactionBehavior.CreateFault(System.ServiceModel.SR.GetString("SFxTransactionAsyncAborted"), "TransactionAborted", true);
                 DiagnosticUtility.ExceptionUtility.TraceHandledException(rpc.Error, TraceEventType.Error);
                 if (DiagnosticUtility.ShouldTraceInformation)
                 {
                     TraceUtility.TraceEvent(TraceEventType.Information, 0xe0009, System.ServiceModel.SR.GetString("TraceCodeTxCompletionStatusCompletedForAsyncAbort", new object[] { rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name }));
                 }
             }
         }
     }
 }
        internal void CheckIfTxCompletedAndUpdateAttached(ref MessageRpc rpc, bool isConcurrent)
        {
            if (rpc.Transaction.Current == null)
            {
                return;
            }

            lock (this.mutex)
            {
                if (!isConcurrent)
                {
                    if (this.shouldReleaseInstance)
                    {
                        this.shouldReleaseInstance = false;
                        if (rpc.Error == null) //we don't want to mask the initial error
                        {
                            rpc.Error = TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true);
                            DiagnosticUtility.TraceHandledException(rpc.Error, TraceEventType.Error);
                            if (DiagnosticUtility.ShouldTraceInformation)
                            {
                                TraceUtility.TraceEvent(TraceEventType.Information,
                                                        TraceCode.TxCompletionStatusCompletedForAsyncAbort,
                                                        SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForAsyncAbort,
                                                                     rpc.Transaction.Current.TransactionInformation.LocalIdentifier,
                                                                     rpc.Operation.Name)
                                                        );
                            }
                        }
                    }

                    if (rpc.Transaction.IsCompleted || (rpc.Error != null))
                    {
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            if (rpc.Error != null)
                            {
                                TraceUtility.TraceEvent(TraceEventType.Information,
                                                        TraceCode.TxCompletionStatusCompletedForError,
                                                        SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForError,
                                                                     rpc.Transaction.Current.TransactionInformation.LocalIdentifier,
                                                                     rpc.Operation.Name)
                                                        );
                            }
                            else
                            {
                                TraceUtility.TraceEvent(TraceEventType.Information,
                                                        TraceCode.TxCompletionStatusCompletedForAutocomplete,
                                                        SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForAutocomplete,
                                                                     rpc.Transaction.Current.TransactionInformation.LocalIdentifier,
                                                                     rpc.Operation.Name)
                                                        );
                            }
                        }

                        this.Attached = null;

                        if (!(waiting == null))
                        {
                            // tx processing requires failfast when state is inconsistent
                            DiagnosticUtility.FailFast("waiting should be null when resetting current");
                        }

                        this.current = null;
                    }
                    else
                    {
                        this.Attached = rpc.Transaction.Current;
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxCompletionStatusRemainsAttached,
                                                    SR.GetString(SR.TraceCodeTxCompletionStatusRemainsAttached,
                                                                 rpc.Transaction.Current.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }
                    }
                }
                else if (!this.pending.ContainsKey(rpc.Transaction.Current))
                {
                    //transaction has been asynchronously aborted
                    if (rpc.Error == null) //we don't want to mask the initial error
                    {
                        rpc.Error = TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true);
                        DiagnosticUtility.TraceHandledException(rpc.Error, TraceEventType.Error);
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxCompletionStatusCompletedForAsyncAbort,
                                                    SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForAsyncAbort,
                                                                 rpc.Transaction.Current.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }
                    }
                }
            }
        }
        internal void ResolveTransaction(ref MessageRpc rpc)
        {
            if (rpc.Operation.HasDefaultUnhandledActionInvoker)
            {
                // we ignore unhandled operations
                return;
            }

            Transaction contextTransaction = null;

            //If we are inside a TransactedReceiveScope in workflow, then we need to look into the PPD and not the InstanceContext
            //to get the contextTransaction
            if (rpc.Operation.IsInsideTransactedReceiveScope)
            {
                // We may want to use an existing transaction for the instance.
                IInstanceTransaction instanceTransaction = rpc.Operation.Invoker as IInstanceTransaction;
                if (instanceTransaction != null)
                {
                    contextTransaction = instanceTransaction.GetTransactionForInstance(rpc.OperationContext);
                }

                if (contextTransaction != null)
                {
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        TraceUtility.TraceEvent(TraceEventType.Information,
                                                TraceCode.TxSourceTxScopeRequiredUsingExistingTransaction,
                                                SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredUsingExistingTransaction,
                                                             contextTransaction.TransactionInformation.LocalIdentifier,
                                                             rpc.Operation.Name)
                                                );
                    }
                }
            }
            else
            {
                contextTransaction = this.GetInstanceContextTransaction(ref rpc);
            }

            Transaction transaction = null;

            try
            {
                transaction = TransactionMessageProperty.TryGetTransaction(rpc.Request);
            }
            catch (TransactionException e)
            {
                DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionUnmarshalFailed, e.Message), FaultCodeConstants.Codes.TransactionUnmarshalingFailed, false));
            }

            if (rpc.Operation.TransactionRequired)
            {
                if (transaction != null)
                {
                    if (this.isTransactedReceiveChannelDispatcher)
                    {
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxSourceTxScopeRequiredIsTransactedTransport,
                                                    SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsTransactedTransport,
                                                                 transaction.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }
                    }
                    else
                    {
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxSourceTxScopeRequiredIsTransactionFlow,
                                                    SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsTransactionFlow,
                                                                 transaction.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }

                        if (PerformanceCounters.PerformanceCountersEnabled)
                        {
                            PerformanceCounters.TxFlowed(PerformanceCounters.GetEndpointDispatcher(), rpc.Operation.Name);
                        }

                        bool sameTransaction = false;
                        if (rpc.Operation.IsInsideTransactedReceiveScope)
                        {
                            sameTransaction = transaction.Equals(contextTransaction);
                        }
                        else
                        {
                            sameTransaction = transaction == contextTransaction;
                        }

                        if (!sameTransaction)
                        {
                            try
                            {
                                transaction = transaction.DependentClone(DependentCloneOption.RollbackIfNotComplete);
                            }
                            catch (TransactionException e)
                            {
                                DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true));
                            }
                        }
                    }
                }
            }
            else
            {
                // We got a transaction from the ChannelHandler.
                // Transport is transacted.
                // But operation doesn't require the transaction, so no one ever will commit it.
                // Because of that we have to commit it here.
                if (transaction != null && this.isTransactedReceiveChannelDispatcher)
                {
                    try
                    {
                        if (null != rpc.TransactedBatchContext)
                        {
                            rpc.TransactedBatchContext.ForceCommit();
                            rpc.TransactedBatchContext = null;
                        }
                        else
                        {
                            TransactionInstanceContextFacet.Complete(transaction, null);
                        }
                    }
                    finally
                    {
                        transaction.Dispose();
                        transaction = null;
                    }
                }
            }

            InstanceContext context = rpc.InstanceContext;

            if (context.Transaction.ShouldReleaseInstance && !this.isConcurrent)
            {
                if (context.Behavior.ReleaseServiceInstanceOnTransactionComplete)
                {
                    context.ReleaseServiceInstance();
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        TraceUtility.TraceEvent(TraceEventType.Information,
                                                TraceCode.TxReleaseServiceInstanceOnCompletion,
                                                SR.GetString(SR.TraceCodeTxReleaseServiceInstanceOnCompletion,
                                                             contextTransaction.TransactionInformation.LocalIdentifier)
                                                );
                    }
                }

                context.Transaction.ShouldReleaseInstance = false;

                if (transaction == null || transaction == contextTransaction)
                {
                    rpc.Transaction.Current = contextTransaction;
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true));
                }
                else
                {
                    contextTransaction = null;
                }
            }

            if (rpc.Operation.TransactionRequired)
            {
                if (transaction == null)
                {
                    if (contextTransaction != null)
                    {
                        transaction = contextTransaction;
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxSourceTxScopeRequiredIsAttachedTransaction,
                                                    SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsAttachedTransaction,
                                                                 transaction.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }
                    }
                    else
                    {
                        transaction = TransactionBehavior.CreateTransaction(this.isolation, this.timeout);
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxSourceTxScopeRequiredIsCreateNewTransaction,
                                                    SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsCreateNewTransaction,
                                                                 transaction.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }
                    }
                }

                if ((this.isolation != IsolationLevel.Unspecified) && (transaction.IsolationLevel != this.isolation))
                {
                    throw TraceUtility.ThrowHelperError(TransactionBehavior.CreateFault
                                                            (SR.GetString(SR.IsolationLevelMismatch2, transaction.IsolationLevel, this.isolation), FaultCodeConstants.Codes.TransactionIsolationLevelMismatch, false), rpc.Request);
                }

                rpc.Transaction.Current = transaction;
                rpc.InstanceContext.Transaction.AddReference(ref rpc, rpc.Transaction.Current, true);

                try
                {
                    rpc.Transaction.Clone = transaction.Clone();
                    if (rpc.Operation.IsInsideTransactedReceiveScope)
                    {
                        //It is because we want to synchronize the dispatcher processing of messages with the commit
                        //processing that is started by the completion of a TransactedReceiveScope. We need to make sure
                        //that all the dispatcher processing is done and we can do that by creating a blocking dependent clone and only
                        //completing it after all of the message processing is done for a given TransactionRpcFacet
                        rpc.Transaction.CreateDependentClone();
                    }
                }
                catch (ObjectDisposedException e)//transaction may be async aborted
                {
                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true));
                }

                rpc.InstanceContext.Transaction.AddReference(ref rpc, rpc.Transaction.Clone, false);

                rpc.OperationContext.TransactionFacet = rpc.Transaction;

                if (!rpc.Operation.TransactionAutoComplete)
                {
                    rpc.Transaction.SetIncomplete();
                }
            }
        }