internal OletxVolatileEnlistment(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction) : base(null, oletxTransaction)
 {
     this.iEnlistmentNotification = enlistmentNotification;
     this.enlistDuringPrepareRequired = (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None;
     this.container = null;
     this.pendingOutcome = TransactionStatus.Active;
     if (DiagnosticTrace.Information)
     {
         EnlistmentTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, EnlistmentType.Volatile, enlistmentOptions);
     }
 }
 internal InternalTransaction(Transaction outcomeSource, OletxTransaction distributedTx)
 {
     if (!TransactionManager._platformValidated)
     {
         TransactionManager.ValidatePlatform();
     }
     this.promotedTransaction = distributedTx;
     this.absoluteTimeout = 0x7fffffffffffffffL;
     this.outcomeSource = outcomeSource;
     this.transactionHash = TransactionManager.TransactionTable.Add(this);
     TransactionState._TransactionStateNonCommittablePromoted.EnterState(this);
     this.promoteState = TransactionState._TransactionStateNonCommittablePromoted;
 }
 public OletxBaseEnlistment(OletxResourceManager oletxResourceManager, OletxTransaction oletxTransaction)
 {
     this.oletxResourceManager = oletxResourceManager;
     this.oletxTransaction = oletxTransaction;
     if (oletxTransaction != null)
     {
         this.enlistmentId = oletxTransaction.realOletxTransaction.enlistmentCount++;
         this.transactionGuidString = oletxTransaction.realOletxTransaction.TxGuid.ToString();
     }
     else
     {
         this.transactionGuidString = Guid.Empty.ToString();
     }
     this.traceIdentifier = EnlistmentTraceIdentifier.Empty;
 }
Пример #4
0
 public OletxBaseEnlistment(OletxResourceManager oletxResourceManager, OletxTransaction oletxTransaction)
 {
     this.oletxResourceManager = oletxResourceManager;
     this.oletxTransaction     = oletxTransaction;
     if (oletxTransaction != null)
     {
         this.enlistmentId          = oletxTransaction.realOletxTransaction.enlistmentCount++;
         this.transactionGuidString = oletxTransaction.realOletxTransaction.TxGuid.ToString();
     }
     else
     {
         this.transactionGuidString = Guid.Empty.ToString();
     }
     this.traceIdentifier = EnlistmentTraceIdentifier.Empty;
 }
Пример #5
0
        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);
        }
        internal RealOletxTransaction(OletxTransactionManager transactionManager, ITransactionShim transactionShim, OutcomeEnlistment outcomeEnlistment, Guid identifier, OletxTransactionIsolationLevel oletxIsoLevel, bool isRoot)
        {
            bool flag = false;

            try
            {
                this.oletxTransactionManager = transactionManager;
                this.transactionShim         = transactionShim;
                this.outcomeEnlistment       = outcomeEnlistment;
                this.txGuid         = identifier;
                this.isolationLevel = OletxTransactionManager.ConvertIsolationLevelFromProxyValue(oletxIsoLevel);
                this.status         = TransactionStatus.Active;
                this.undisposedOletxTransactionCount       = 0;
                this.phase0EnlistVolatilementContainerList = null;
                this.phase1EnlistVolatilementContainer     = null;
                this.tooLateForEnlistments = false;
                this.internalTransaction   = null;
                this.creationTime          = DateTime.UtcNow;
                this.lastStateChangeTime   = this.creationTime;
                this.internalClone         = new OletxTransaction(this);
                if (this.outcomeEnlistment != null)
                {
                    this.outcomeEnlistment.SetRealTransaction(this);
                }
                else
                {
                    this.status = TransactionStatus.InDoubt;
                }
                if (DiagnosticTrace.HaveListeners)
                {
                    DiagnosticTrace.TraceTransfer(this.txGuid);
                }
                flag = true;
            }
            finally
            {
                if (!flag && (this.outcomeEnlistment != null))
                {
                    this.outcomeEnlistment.UnregisterOutcomeCallback();
                    this.outcomeEnlistment = null;
                }
            }
        }
 internal RealOletxTransaction(OletxTransactionManager transactionManager, ITransactionShim transactionShim, OutcomeEnlistment outcomeEnlistment, Guid identifier, OletxTransactionIsolationLevel oletxIsoLevel, bool isRoot)
 {
     bool flag = false;
     try
     {
         this.oletxTransactionManager = transactionManager;
         this.transactionShim = transactionShim;
         this.outcomeEnlistment = outcomeEnlistment;
         this.txGuid = identifier;
         this.isolationLevel = OletxTransactionManager.ConvertIsolationLevelFromProxyValue(oletxIsoLevel);
         this.status = TransactionStatus.Active;
         this.undisposedOletxTransactionCount = 0;
         this.phase0EnlistVolatilementContainerList = null;
         this.phase1EnlistVolatilementContainer = null;
         this.tooLateForEnlistments = false;
         this.internalTransaction = null;
         this.creationTime = DateTime.UtcNow;
         this.lastStateChangeTime = this.creationTime;
         this.internalClone = new OletxTransaction(this);
         if (this.outcomeEnlistment != null)
         {
             this.outcomeEnlistment.SetRealTransaction(this);
         }
         else
         {
             this.status = TransactionStatus.InDoubt;
         }
         if (DiagnosticTrace.HaveListeners)
         {
             DiagnosticTrace.TraceTransfer(this.txGuid);
         }
         flag = true;
     }
     finally
     {
         if (!flag && (this.outcomeEnlistment != null))
         {
             this.outcomeEnlistment.UnregisterOutcomeCallback();
             this.outcomeEnlistment = null;
         }
     }
 }
Пример #8
0
        // 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;
        }
 internal static byte[] GetTransmitterPropagationToken(OletxTransaction oletxTx)
 {
     CoTaskMemHandle propgationToken = null;
     byte[] destination = null;
     uint propagationTokeSize = 0;
     try
     {
         oletxTx.realOletxTransaction.TransactionShim.GetPropagationToken(out propagationTokeSize, out propgationToken);
         destination = new byte[propagationTokeSize];
         Marshal.Copy(propgationToken.DangerousGetHandle(), destination, 0, Convert.ToInt32(propagationTokeSize));
     }
     catch (COMException exception)
     {
         OletxTransactionManager.ProxyException(exception);
         throw;
     }
     finally
     {
         if (propgationToken != null)
         {
             propgationToken.Close();
         }
     }
     return destination;
 }
 public static Transaction GetTransactionFromExportCookie(byte[] cookie)
 {
     if (!TransactionManager._platformValidated)
     {
         TransactionManager.ValidatePlatform();
     }
     if (cookie == null)
     {
         throw new ArgumentNullException("cookie");
     }
     if (cookie.Length < 0x20)
     {
         throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "cookie");
     }
     if (DiagnosticTrace.Verbose)
     {
         MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromExportCookie");
     }
     byte[] destinationArray = new byte[cookie.Length];
     Array.Copy(cookie, destinationArray, cookie.Length);
     cookie = destinationArray;
     Transaction transaction = null;
     ITransactionShim transactionShim = null;
     Guid empty = Guid.Empty;
     OletxTransactionIsolationLevel isolationLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
     OutcomeEnlistment target = null;
     OletxTransaction oletx = null;
     byte[] b = new byte[0x10];
     for (int i = 0; i < b.Length; i++)
     {
         b[i] = cookie[i + 0x10];
     }
     Guid transactionIdentifier = new Guid(b);
     transaction = TransactionManager.FindPromotedTransaction(transactionIdentifier);
     if (null != transaction)
     {
         if (DiagnosticTrace.Verbose)
         {
             MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromExportCookie");
         }
         return transaction;
     }
     RealOletxTransaction realOletxTransaction = null;
     OletxTransactionManager distributedTransactionManager = TransactionManager.DistributedTransactionManager;
     distributedTransactionManager.dtcTransactionManagerLock.AcquireReaderLock(-1);
     try
     {
         target = new OutcomeEnlistment();
         IntPtr zero = IntPtr.Zero;
         RuntimeHelpers.PrepareConstrainedRegions();
         try
         {
             zero = HandleTable.AllocHandle(target);
             distributedTransactionManager.DtcTransactionManager.ProxyShimFactory.Import(Convert.ToUInt32(cookie.Length), cookie, zero, out empty, out isolationLevel, out transactionShim);
         }
         finally
         {
             if ((transactionShim == null) && (zero != IntPtr.Zero))
             {
                 HandleTable.FreeHandle(zero);
             }
         }
     }
     catch (COMException exception)
     {
         OletxTransactionManager.ProxyException(exception);
         throw TransactionManagerCommunicationException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), exception);
     }
     finally
     {
         distributedTransactionManager.dtcTransactionManagerLock.ReleaseReaderLock();
     }
     realOletxTransaction = new RealOletxTransaction(distributedTransactionManager, transactionShim, target, empty, isolationLevel, false);
     oletx = new OletxTransaction(realOletxTransaction);
     transaction = TransactionManager.FindOrCreatePromotedTransaction(transactionIdentifier, oletx);
     if (DiagnosticTrace.Verbose)
     {
         MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromExportCookie");
     }
     return transaction;
 }
 public static Transaction GetTransactionFromDtcTransaction(IDtcTransaction transactionNative)
 {
     OletxXactTransInfo info;
     if (!TransactionManager._platformValidated)
     {
         TransactionManager.ValidatePlatform();
     }
     bool flag = false;
     ITransactionShim transactionShim = null;
     Guid empty = Guid.Empty;
     OletxTransactionIsolationLevel isolationLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
     OutcomeEnlistment target = null;
     RealOletxTransaction realOletxTransaction = null;
     OletxTransaction oletx = null;
     if (transactionNative == null)
     {
         throw new ArgumentNullException("transactionNative");
     }
     Transaction transaction = null;
     if (DiagnosticTrace.Verbose)
     {
         MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromDtc");
     }
     ITransactionNativeInternal internal2 = transactionNative as ITransactionNativeInternal;
     if (internal2 == null)
     {
         throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "transactionNative");
     }
     try
     {
         internal2.GetTransactionInfo(out info);
     }
     catch (COMException exception2)
     {
         if (System.Transactions.Oletx.NativeMethods.XACT_E_NOTRANSACTION != exception2.ErrorCode)
         {
             throw;
         }
         flag = true;
         info.uow = Guid.Empty;
     }
     OletxTransactionManager distributedTransactionManager = TransactionManager.DistributedTransactionManager;
     if (!flag)
     {
         transaction = TransactionManager.FindPromotedTransaction(info.uow);
         if (null != transaction)
         {
             if (DiagnosticTrace.Verbose)
             {
                 MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromDtcTransaction");
             }
             return transaction;
         }
         distributedTransactionManager.dtcTransactionManagerLock.AcquireReaderLock(-1);
         try
         {
             target = new OutcomeEnlistment();
             IntPtr zero = IntPtr.Zero;
             RuntimeHelpers.PrepareConstrainedRegions();
             try
             {
                 zero = HandleTable.AllocHandle(target);
                 distributedTransactionManager.DtcTransactionManager.ProxyShimFactory.CreateTransactionShim(transactionNative, zero, out empty, out isolationLevel, out transactionShim);
             }
             finally
             {
                 if ((transactionShim == null) && (zero != IntPtr.Zero))
                 {
                     HandleTable.FreeHandle(zero);
                 }
             }
         }
         catch (COMException exception)
         {
             OletxTransactionManager.ProxyException(exception);
             throw;
         }
         finally
         {
             distributedTransactionManager.dtcTransactionManagerLock.ReleaseReaderLock();
         }
         realOletxTransaction = new RealOletxTransaction(distributedTransactionManager, transactionShim, target, empty, isolationLevel, false);
         oletx = new OletxTransaction(realOletxTransaction);
         transaction = TransactionManager.FindOrCreatePromotedTransaction(info.uow, oletx);
     }
     else
     {
         realOletxTransaction = new RealOletxTransaction(distributedTransactionManager, null, null, empty, OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE, false);
         oletx = new OletxTransaction(realOletxTransaction);
         transaction = new Transaction(oletx);
         TransactionManager.FireDistributedTransactionStarted(transaction);
         oletx.savedLtmPromotedTransaction = transaction;
         InternalTransaction.DistributedTransactionOutcome(transaction.internalTransaction, TransactionStatus.InDoubt);
     }
     if (DiagnosticTrace.Verbose)
     {
         MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromDtc");
     }
     return transaction;
 }
        internal IPromotedEnlistment CommonEnlistVolatile(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction)
        {
            OletxVolatileEnlistment enlistment = null;
            bool flag2 = false;
            bool flag  = false;
            OletxPhase0VolatileEnlistmentContainer target    = null;
            OletxPhase1VolatileEnlistmentContainer container = null;
            IntPtr                zero            = IntPtr.Zero;
            IVoterBallotShim      voterBallotShim = null;
            IPhase0EnlistmentShim shim            = null;
            bool flag3 = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                lock (this)
                {
                    enlistment = new OletxVolatileEnlistment(enlistmentNotification, enlistmentOptions, oletxTransaction);
                    if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
                    {
                        if (this.phase0EnlistVolatilementContainerList == null)
                        {
                            this.phase0EnlistVolatilementContainerList = new ArrayList(1);
                        }
                        if (this.phase0EnlistVolatilementContainerList.Count == 0)
                        {
                            target = new OletxPhase0VolatileEnlistmentContainer(this);
                            flag   = true;
                        }
                        else
                        {
                            target = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer;
                            if (!target.NewEnlistmentsAllowed)
                            {
                                target = new OletxPhase0VolatileEnlistmentContainer(this);
                                flag   = true;
                            }
                            else
                            {
                                flag = false;
                            }
                        }
                        if (flag)
                        {
                            zero = HandleTable.AllocHandle(target);
                        }
                    }
                    else if (this.phase1EnlistVolatilementContainer == null)
                    {
                        flag2     = true;
                        container = new OletxPhase1VolatileEnlistmentContainer(this)
                        {
                            voterHandle = HandleTable.AllocHandle(container)
                        };
                    }
                    else
                    {
                        flag2     = false;
                        container = this.phase1EnlistVolatilementContainer;
                    }
                    try
                    {
                        if (flag)
                        {
                            lock (target)
                            {
                                this.transactionShim.Phase0Enlist(zero, out shim);
                                target.Phase0EnlistmentShim = shim;
                            }
                        }
                        if (flag2)
                        {
                            this.transactionShim.CreateVoter(container.voterHandle, out voterBallotShim);
                            flag3 = true;
                            container.VoterBallotShim = voterBallotShim;
                        }
                        if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
                        {
                            target.AddEnlistment(enlistment);
                            if (flag)
                            {
                                this.phase0EnlistVolatilementContainerList.Add(target);
                            }
                            return(enlistment);
                        }
                        container.AddEnlistment(enlistment);
                        if (flag2)
                        {
                            this.phase1EnlistVolatilementContainer = container;
                        }
                        return(enlistment);
                    }
                    catch (COMException exception)
                    {
                        OletxTransactionManager.ProxyException(exception);
                        throw;
                    }
                    return(enlistment);
                }
            }
            finally
            {
                if ((zero != IntPtr.Zero) && (target.Phase0EnlistmentShim == null))
                {
                    HandleTable.FreeHandle(zero);
                }
                if ((!flag3 && (container != null)) && ((container.voterHandle != IntPtr.Zero) && flag2))
                {
                    HandleTable.FreeHandle(container.voterHandle);
                }
            }
            return(enlistment);
        }
 internal IPromotedEnlistment CommonEnlistVolatile(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction)
 {
     OletxVolatileEnlistment enlistment = null;
     bool flag2 = false;
     bool flag = false;
     OletxPhase0VolatileEnlistmentContainer target = null;
     OletxPhase1VolatileEnlistmentContainer container = null;
     IntPtr zero = IntPtr.Zero;
     IVoterBallotShim voterBallotShim = null;
     IPhase0EnlistmentShim shim = null;
     bool flag3 = false;
     RuntimeHelpers.PrepareConstrainedRegions();
     try
     {
         lock (this)
         {
             enlistment = new OletxVolatileEnlistment(enlistmentNotification, enlistmentOptions, oletxTransaction);
             if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
             {
                 if (this.phase0EnlistVolatilementContainerList == null)
                 {
                     this.phase0EnlistVolatilementContainerList = new ArrayList(1);
                 }
                 if (this.phase0EnlistVolatilementContainerList.Count == 0)
                 {
                     target = new OletxPhase0VolatileEnlistmentContainer(this);
                     flag = true;
                 }
                 else
                 {
                     target = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer;
                     if (!target.NewEnlistmentsAllowed)
                     {
                         target = new OletxPhase0VolatileEnlistmentContainer(this);
                         flag = true;
                     }
                     else
                     {
                         flag = false;
                     }
                 }
                 if (flag)
                 {
                     zero = HandleTable.AllocHandle(target);
                 }
             }
             else if (this.phase1EnlistVolatilementContainer == null)
             {
                 flag2 = true;
                 container = new OletxPhase1VolatileEnlistmentContainer(this) {
                     voterHandle = HandleTable.AllocHandle(container)
                 };
             }
             else
             {
                 flag2 = false;
                 container = this.phase1EnlistVolatilementContainer;
             }
             try
             {
                 if (flag)
                 {
                     lock (target)
                     {
                         this.transactionShim.Phase0Enlist(zero, out shim);
                         target.Phase0EnlistmentShim = shim;
                     }
                 }
                 if (flag2)
                 {
                     this.transactionShim.CreateVoter(container.voterHandle, out voterBallotShim);
                     flag3 = true;
                     container.VoterBallotShim = voterBallotShim;
                 }
                 if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
                 {
                     target.AddEnlistment(enlistment);
                     if (flag)
                     {
                         this.phase0EnlistVolatilementContainerList.Add(target);
                     }
                     return enlistment;
                 }
                 container.AddEnlistment(enlistment);
                 if (flag2)
                 {
                     this.phase1EnlistVolatilementContainer = container;
                 }
                 return enlistment;
             }
             catch (COMException exception)
             {
                 OletxTransactionManager.ProxyException(exception);
                 throw;
             }
             return enlistment;
         }
     }
     finally
     {
         if ((zero != IntPtr.Zero) && (target.Phase0EnlistmentShim == null))
         {
             HandleTable.FreeHandle(zero);
         }
         if ((!flag3 && (container != null)) && ((container.voterHandle != IntPtr.Zero) && flag2))
         {
             HandleTable.FreeHandle(container.voterHandle);
         }
     }
     return enlistment;
 }
 internal OletxEnlistment EnlistDurable(OletxTransaction oletxTransaction, bool canDoSinglePhase, IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions)
 {
     IResourceManagerShim resourceManagerShim = null;
     IPhase0EnlistmentShim shim2 = null;
     IEnlistmentShim enlistmentShim = null;
     IntPtr zero = IntPtr.Zero;
     bool flag3 = false;
     bool flag2 = false;
     OletxEnlistment target = new OletxEnlistment(canDoSinglePhase, enlistmentNotification, oletxTransaction.RealTransaction.TxGuid, enlistmentOptions, this, oletxTransaction);
     bool flag = false;
     RuntimeHelpers.PrepareConstrainedRegions();
     try
     {
         if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
         {
             RuntimeHelpers.PrepareConstrainedRegions();
             try
             {
             }
             finally
             {
                 oletxTransaction.RealTransaction.IncrementUndecidedEnlistments();
                 flag2 = true;
             }
         }
         lock (target)
         {
             RuntimeHelpers.PrepareConstrainedRegions();
             try
             {
                 resourceManagerShim = this.ResourceManagerShim;
                 if (resourceManagerShim == null)
                 {
                     throw TransactionManagerCommunicationException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), null);
                 }
                 if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
                 {
                     zero = HandleTable.AllocHandle(target);
                     RuntimeHelpers.PrepareConstrainedRegions();
                     try
                     {
                     }
                     finally
                     {
                         oletxTransaction.RealTransaction.TransactionShim.Phase0Enlist(zero, out shim2);
                         flag3 = true;
                     }
                     target.Phase0EnlistmentShim = shim2;
                 }
                 target.phase1Handle = HandleTable.AllocHandle(target);
                 resourceManagerShim.Enlist(oletxTransaction.RealTransaction.TransactionShim, target.phase1Handle, out enlistmentShim);
                 target.EnlistmentShim = enlistmentShim;
             }
             catch (COMException exception)
             {
                 if (System.Transactions.Oletx.NativeMethods.XACT_E_TOOMANY_ENLISTMENTS == exception.ErrorCode)
                 {
                     throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("OletxTooManyEnlistments"), exception);
                 }
                 OletxTransactionManager.ProxyException(exception);
                 throw;
             }
             finally
             {
                 if (target.EnlistmentShim == null)
                 {
                     if ((zero != IntPtr.Zero) && !flag3)
                     {
                         HandleTable.FreeHandle(zero);
                     }
                     if (target.phase1Handle != IntPtr.Zero)
                     {
                         HandleTable.FreeHandle(target.phase1Handle);
                     }
                 }
             }
         }
         flag = true;
     }
     finally
     {
         if ((!flag && ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)) && flag2)
         {
             oletxTransaction.RealTransaction.DecrementUndecidedEnlistments();
         }
     }
     return target;
 }
Пример #15
0
        internal OletxVolatileEnlistment(
            IEnlistmentNotificationInternal enlistmentNotification,
            EnlistmentOptions enlistmentOptions,
            OletxTransaction oletxTransaction
            ) : base( null, oletxTransaction )
        {
            this.iEnlistmentNotification = enlistmentNotification;
            this.enlistDuringPrepareRequired = (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0;

            // We get a container when we are asked to vote.
            this.container = null;

            pendingOutcome = TransactionStatus.Active;

            if ( DiagnosticTrace.Information )
            {
                EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    this.InternalTraceIdentifier,
                    EnlistmentType.Volatile,
                    enlistmentOptions
                    );
            }
        }
Пример #16
0
 internal OletxVolatileEnlistment(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction) : base(null, oletxTransaction)
 {
     this.iEnlistmentNotification     = enlistmentNotification;
     this.enlistDuringPrepareRequired = (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None;
     this.container      = null;
     this.pendingOutcome = TransactionStatus.Active;
     if (DiagnosticTrace.Information)
     {
         EnlistmentTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, EnlistmentType.Volatile, enlistmentOptions);
     }
 }
        public static Transaction GetTransactionFromDtcTransaction(
            IDtcTransaction transactionNative
            )
        {
            if ( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();

            bool tooLate = false;
            ITransactionShim transactionShim = null;
            Guid txIdentifier = Guid.Empty;
            OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
            OutcomeEnlistment outcomeEnlistment = null;
            RealOletxTransaction realTx = null;
            OletxTransaction oleTx = null;

            if ( null == transactionNative )
            {
                throw new ArgumentNullException( "transactionNative" );
            }

            Transaction transaction = null;

            if ( DiagnosticTrace.Verbose )
            {
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromDtc"
                    );
            }

            // Let's get the guid of the transaction from the proxy to see if we already
            // have an object.
            ITransactionNativeInternal myTransactionNative = transactionNative as ITransactionNativeInternal;
            if ( null == myTransactionNative )
            {
                throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "transactionNative" );
            }

            OletxXactTransInfo xactInfo;
            try
            {
                myTransactionNative.GetTransactionInfo( out xactInfo );
            }
            catch ( COMException ex )
            {
                if ( Oletx.NativeMethods.XACT_E_NOTRANSACTION != ex.ErrorCode )
                {
                    throw;
                }

                // If we get here, the transaction has appraently already been committed or aborted.  Allow creation of the
                // OletxTransaction, but it will be marked with a status of InDoubt and attempts to get its Identifier
                // property will result in a TransactionException.
                tooLate = true;
                xactInfo.uow = Guid.Empty;

            }

            OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager;
            if ( ! tooLate )
            {
                // First check to see if there is a promoted LTM transaction with the same ID.  If there
                // is, just return that.
                transaction = TransactionManager.FindPromotedTransaction( xactInfo.uow );
                if ( null != transaction )
                {
                    if ( DiagnosticTrace.Verbose )
                    {
                        MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                            "TransactionInterop.GetTransactionFromDtcTransaction"
                            );
                    }
                    return transaction;
                }

                // We need to create a new RealOletxTransaction...
                oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 );
                try
                {
                    outcomeEnlistment = new OutcomeEnlistment();
                    IntPtr outcomeEnlistmentHandle = IntPtr.Zero;
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try
                    {
                        outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment );
                        oletxTm.DtcTransactionManager.ProxyShimFactory.CreateTransactionShim(
                            transactionNative,
                            outcomeEnlistmentHandle,
                            out txIdentifier,
                            out oletxIsoLevel,
                            out transactionShim );
                    }
                    finally
                    {
                        if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero )
                        {
                            HandleTable.FreeHandle( outcomeEnlistmentHandle );
                        }
                    }
                }
                catch ( COMException comException )
                {
                    OletxTransactionManager.ProxyException( comException );
                    throw;
                }
                finally
                {
                    oletxTm.dtcTransactionManagerLock.ReleaseReaderLock();
                }

                // We need to create a new RealOletxTransaction.
                realTx = new RealOletxTransaction(
                    oletxTm,
                    transactionShim,
                    outcomeEnlistment,
                    txIdentifier,
                    oletxIsoLevel,
                    false );

                oleTx = new OletxTransaction( realTx );

                // If a transaction is found then FindOrCreate will Dispose the oletx
                // created.
                transaction = TransactionManager.FindOrCreatePromotedTransaction( xactInfo.uow, oleTx );
            }
            else
            {
                // It was too late to do a clone of the provided ITransactionNative, so we are just going to
                // create a RealOletxTransaction without a transaction shim or outcome enlistment.
                realTx = new RealOletxTransaction(
                    oletxTm,
                    null,
                    null,
                    txIdentifier,
                    OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE,
                    false );

                oleTx = new OletxTransaction( realTx );
                transaction = new Transaction( oleTx );
                TransactionManager.FireDistributedTransactionStarted( transaction );
                oleTx.savedLtmPromotedTransaction = transaction;

                InternalTransaction.DistributedTransactionOutcome(transaction.internalTransaction, TransactionStatus.InDoubt);
            }


            if ( DiagnosticTrace.Verbose )
            {
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromDtc"
                    );
            }
            return transaction;
        }
        internal static byte[] GetTransmitterPropagationToken(
            OletxTransaction oletxTx
            )
        {
            byte[] propagationToken = null;
            CoTaskMemHandle propagationTokenBuffer = null;
            UInt32 tokenSize = 0;

            try
            {
                oletxTx.realOletxTransaction.TransactionShim.GetPropagationToken(
                    out tokenSize,
                    out propagationTokenBuffer );
                propagationToken = new byte[tokenSize];
                Marshal.Copy( propagationTokenBuffer.DangerousGetHandle(), propagationToken, 0, Convert.ToInt32(tokenSize) );
            }
            catch (COMException comException)
            {
                OletxTransactionManager.ProxyException( comException );
                throw;
            }
            finally
            {
                if ( null != propagationTokenBuffer )
                {
                    propagationTokenBuffer.Close();
                }
            }

            return propagationToken;
        }
        public static Transaction GetTransactionFromExportCookie(
            byte[] cookie
            )
        {
            if ( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();

            if ( null == cookie )
            {
                throw new ArgumentNullException( "cookie" );
            }

            if ( cookie.Length < 32 )
            {
                throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "cookie" );
            }

            if ( DiagnosticTrace.Verbose )
            {
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromExportCookie"
                    );
            }

            byte[] cookieCopy = new byte[cookie.Length];
            Array.Copy(cookie, cookieCopy, cookie.Length);
            cookie = cookieCopy;

            Transaction transaction = null;
            ITransactionShim transactionShim = null;
            Guid txIdentifier = Guid.Empty;
            OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
            OutcomeEnlistment outcomeEnlistment = null;
            OletxTransaction oleTx = null;

            // Extract the transaction guid from the propagation token to see if we already have a
            // transaction object for the transaction.
            byte[] guidByteArray = new byte[16];
            for (int i = 0; i < guidByteArray.Length; i++ )
            {
                // In a cookie, the transaction guid is preceeded by a signature guid.
                guidByteArray[i] = cookie[i + 16];
            }

            Guid txId = new Guid( guidByteArray );

            // First check to see if there is a promoted LTM transaction with the same ID.  If there
            // is, just return that.
            transaction = TransactionManager.FindPromotedTransaction( txId );
            if ( null != transaction )
            {
                if ( DiagnosticTrace.Verbose )
                {
                    MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                        "TransactionInterop.GetTransactionFromExportCookie"
                        );
                }
                return transaction;
            }

            // We need to create a new transaction
            RealOletxTransaction realTx = null;
            OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager;

            oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 );
            try
            {
                outcomeEnlistment = new OutcomeEnlistment();
                IntPtr outcomeEnlistmentHandle = IntPtr.Zero;
                RuntimeHelpers.PrepareConstrainedRegions();
                try
                {
                    outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment );
                    oletxTm.DtcTransactionManager.ProxyShimFactory.Import(
                        Convert.ToUInt32(cookie.Length),
                        cookie,
                        outcomeEnlistmentHandle,
                        out txIdentifier,
                        out oletxIsoLevel,
                        out transactionShim );
                }
                finally
                {
                    if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero )
                    {
                        HandleTable.FreeHandle( outcomeEnlistmentHandle );
                    }
                }
            }
            catch ( COMException comException )
            {
                OletxTransactionManager.ProxyException( comException );

                // We are unsure of what the exception may mean.  It is possible that 
                // we could get E_FAIL when trying to contact a transaction manager that is
                // being blocked by a fire wall.  On the other hand we may get a COMException
                // based on bad data.  The more common situation is that the data is fine
                // (since it is generated by Microsoft code) and the problem is with 
                // communication.  So in this case we default for unknown exceptions to
                // assume that the problem is with communication.
                throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException );
            }
            finally
            {
                oletxTm.dtcTransactionManagerLock.ReleaseReaderLock();
            }

            // We need to create a new RealOletxTransaction.
            realTx = new RealOletxTransaction(
                oletxTm,
                transactionShim,
                outcomeEnlistment,
                txIdentifier,
                oletxIsoLevel,
                false );

            // Now create the associated OletxTransaction.
            oleTx = new OletxTransaction( realTx );

            // If a transaction is found then FindOrCreate will Dispose the oletx
            // created.
            transaction = TransactionManager.FindOrCreatePromotedTransaction( txId, oleTx );

            if ( DiagnosticTrace.Verbose )
            {
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromExportCookie"
                    );
            }

            return transaction;
        }
 internal IPromotedEnlistment EnlistVolatile(ISinglePhaseNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction)
 {
     return(this.CommonEnlistVolatile(enlistmentNotification, enlistmentOptions, oletxTransaction));
 }
        // 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;
        }
 internal OletxEnlistment(bool canDoSinglePhase, IEnlistmentNotificationInternal enlistmentNotification, Guid transactionGuid, EnlistmentOptions enlistmentOptions, OletxResourceManager oletxResourceManager, OletxTransaction oletxTransaction) : base(oletxResourceManager, oletxTransaction)
 {
     this.transactionGuid = Guid.Empty;
     this.phase1Handle = IntPtr.Zero;
     this.enlistmentShim = null;
     this.phase0Shim = null;
     this.canDoSinglePhase = canDoSinglePhase;
     this.iEnlistmentNotification = enlistmentNotification;
     this.state = OletxEnlistmentState.Active;
     this.transactionGuid = transactionGuid;
     this.proxyPrepareInfoByteArray = null;
     if (DiagnosticTrace.Information)
     {
         EnlistmentTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, EnlistmentType.Durable, enlistmentOptions);
     }
     base.AddToEnlistmentTable();
 }
 internal OletxEnlistment(bool canDoSinglePhase, IEnlistmentNotificationInternal enlistmentNotification, Guid transactionGuid, EnlistmentOptions enlistmentOptions, OletxResourceManager oletxResourceManager, OletxTransaction oletxTransaction) : base(oletxResourceManager, oletxTransaction)
 {
     this.transactionGuid         = Guid.Empty;
     this.phase1Handle            = IntPtr.Zero;
     this.enlistmentShim          = null;
     this.phase0Shim              = null;
     this.canDoSinglePhase        = canDoSinglePhase;
     this.iEnlistmentNotification = enlistmentNotification;
     this.state                     = OletxEnlistmentState.Active;
     this.transactionGuid           = transactionGuid;
     this.proxyPrepareInfoByteArray = null;
     if (DiagnosticTrace.Information)
     {
         EnlistmentTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.InternalTraceIdentifier, EnlistmentType.Durable, enlistmentOptions);
     }
     base.AddToEnlistmentTable();
 }
 internal IPromotedEnlistment EnlistVolatile(ISinglePhaseNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction)
 {
     return this.CommonEnlistVolatile(enlistmentNotification, enlistmentOptions, oletxTransaction);
 }
Пример #25
0
        internal OletxEnlistment(
            bool canDoSinglePhase,
            IEnlistmentNotificationInternal enlistmentNotification,
            Guid transactionGuid,
            EnlistmentOptions enlistmentOptions,
            OletxResourceManager oletxResourceManager,
            OletxTransaction oletxTransaction
            ) : base( oletxResourceManager, oletxTransaction )
        {
            Guid myGuid = Guid.Empty;

            // This will get set later by the creator of this object after it
            // has enlisted with the proxy.
            this.enlistmentShim = null;
            this.phase0Shim = null;

            this.canDoSinglePhase = canDoSinglePhase;
            this.iEnlistmentNotification = enlistmentNotification;
            this.state = OletxEnlistmentState.Active;
            this.transactionGuid = transactionGuid;

            this.proxyPrepareInfoByteArray = null;

            if ( DiagnosticTrace.Information )
            {
                EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    this.InternalTraceIdentifier,
                    EnlistmentType.Durable,
                    enlistmentOptions
                    );
            }

            // Always do this last incase anything earlier fails.
            AddToEnlistmentTable();
        }
Пример #26
0
        internal OletxEnlistment EnlistDurable(OletxTransaction oletxTransaction, bool canDoSinglePhase, IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions)
        {
            IResourceManagerShim  resourceManagerShim = null;
            IPhase0EnlistmentShim shim2          = null;
            IEnlistmentShim       enlistmentShim = null;
            IntPtr          zero   = IntPtr.Zero;
            bool            flag3  = false;
            bool            flag2  = false;
            OletxEnlistment target = new OletxEnlistment(canDoSinglePhase, enlistmentNotification, oletxTransaction.RealTransaction.TxGuid, enlistmentOptions, this, oletxTransaction);
            bool            flag   = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
                {
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try
                    {
                    }
                    finally
                    {
                        oletxTransaction.RealTransaction.IncrementUndecidedEnlistments();
                        flag2 = true;
                    }
                }
                lock (target)
                {
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try
                    {
                        resourceManagerShim = this.ResourceManagerShim;
                        if (resourceManagerShim == null)
                        {
                            throw TransactionManagerCommunicationException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), null);
                        }
                        if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
                        {
                            zero = HandleTable.AllocHandle(target);
                            RuntimeHelpers.PrepareConstrainedRegions();
                            try
                            {
                            }
                            finally
                            {
                                oletxTransaction.RealTransaction.TransactionShim.Phase0Enlist(zero, out shim2);
                                flag3 = true;
                            }
                            target.Phase0EnlistmentShim = shim2;
                        }
                        target.phase1Handle = HandleTable.AllocHandle(target);
                        resourceManagerShim.Enlist(oletxTransaction.RealTransaction.TransactionShim, target.phase1Handle, out enlistmentShim);
                        target.EnlistmentShim = enlistmentShim;
                    }
                    catch (COMException exception)
                    {
                        if (System.Transactions.Oletx.NativeMethods.XACT_E_TOOMANY_ENLISTMENTS == exception.ErrorCode)
                        {
                            throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("OletxTooManyEnlistments"), exception);
                        }
                        OletxTransactionManager.ProxyException(exception);
                        throw;
                    }
                    finally
                    {
                        if (target.EnlistmentShim == null)
                        {
                            if ((zero != IntPtr.Zero) && !flag3)
                            {
                                HandleTable.FreeHandle(zero);
                            }
                            if (target.phase1Handle != IntPtr.Zero)
                            {
                                HandleTable.FreeHandle(target.phase1Handle);
                            }
                        }
                    }
                }
                flag = true;
            }
            finally
            {
                if ((!flag && ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)) && flag2)
                {
                    oletxTransaction.RealTransaction.DecrementUndecidedEnlistments();
                }
            }
            return(target);
        }
Пример #27
0
 internal IPromotedEnlistment EnlistVolatile(
     IEnlistmentNotificationInternal enlistmentNotification,
     EnlistmentOptions enlistmentOptions,
     OletxTransaction oletxTransaction
     )
 {
     IPromotedEnlistment enlistment = CommonEnlistVolatile(
         enlistmentNotification,
         enlistmentOptions,
         oletxTransaction
         );
     return enlistment;
 }
Пример #28
0
        // Common constructor used by all types of constructors
        // Create a clean and fresh transaction.
        internal RealOletxTransaction(OletxTransactionManager transactionManager, 
            ITransactionShim transactionShim,
            OutcomeEnlistment outcomeEnlistment,
            Guid identifier,
            OletxTransactionIsolationLevel oletxIsoLevel,
            bool isRoot )
        {
            bool successful = false;

            try
            {
                // initialize the member fields
                this.oletxTransactionManager = transactionManager;
                this.transactionShim = transactionShim;
                this.outcomeEnlistment = outcomeEnlistment;
                this.txGuid = identifier;
                this.isolationLevel = OletxTransactionManager.ConvertIsolationLevelFromProxyValue( oletxIsoLevel );
                this.status = TransactionStatus.Active;
                this.undisposedOletxTransactionCount = 0;
                this.phase0EnlistVolatilementContainerList = null;
                this.phase1EnlistVolatilementContainer = null;
                this.tooLateForEnlistments = false;
                this.internalTransaction = null;

                this.creationTime = DateTime.UtcNow;
                this.lastStateChangeTime = this.creationTime;

                // Connect this object with the OutcomeEnlistment.
                this.internalClone = new OletxTransaction( this );

                // We have have been created without an outcome enlistment if it was too late to create
                // a clone from the ITransactionNative that we were created from.
                if ( null != this.outcomeEnlistment )
                {
                    this.outcomeEnlistment.SetRealTransaction( this );
                }
                else
                {
                    this.status = TransactionStatus.InDoubt;
                }

                if ( DiagnosticTrace.HaveListeners )
                {
                    DiagnosticTrace.TraceTransfer(this.txGuid);
                }

                successful = true;
            }
            finally
            {
                if (!successful)
                {
                    if (this.outcomeEnlistment != null)
                    {
                        this.outcomeEnlistment.UnregisterOutcomeCallback();
                        this.outcomeEnlistment = null;
                    }
                }
            }
               
        }
 internal Transaction(OletxTransaction oleTransaction)
 {
     this.isoLevel = oleTransaction.IsolationLevel;
     this.internalTransaction = new InternalTransaction(this, oleTransaction);
     this.cloneId = Interlocked.Increment(ref this.internalTransaction.cloneCount);
 }
Пример #30
0
        internal OletxEnlistment EnlistDurable(
            OletxTransaction oletxTransaction,
            bool canDoSinglePhase,
            IEnlistmentNotificationInternal enlistmentNotification,
            EnlistmentOptions enlistmentOptions
            )
        {
            IResourceManagerShim localResourceManagerShim = null;

            Debug.Assert( null != oletxTransaction, "Argument is null" );
            Debug.Assert( null != enlistmentNotification, "Argument is null" );

            IEnlistmentShim enlistmentShim = null;
            IPhase0EnlistmentShim phase0Shim = null;
            Guid txUow = Guid.Empty;
            IntPtr handlePhase0 = IntPtr.Zero;
            bool phase0EnlistSucceeded = false;
            bool undecidedEnlistmentsIncremented = false;

            // Create our enlistment object.
            OletxEnlistment enlistment = new OletxEnlistment(
                canDoSinglePhase,
                enlistmentNotification,
                oletxTransaction.RealTransaction.TxGuid,
                enlistmentOptions,
                this,
                oletxTransaction
                );

            bool enlistmentSucceeded = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                if ( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 )
                {
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try { }
                    finally
                    {                    
                        oletxTransaction.RealTransaction.IncrementUndecidedEnlistments();
                        undecidedEnlistmentsIncremented = true;
                    }
                }

                // This entire sequense needs to be executed before we can go on.
                lock ( enlistment )
                {
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try
                    {
                        // Do the enlistment on the proxy.
                        localResourceManagerShim = this.ResourceManagerShim;
                        if ( null == localResourceManagerShim )
                        {
                            // The TM must be down.  Throw the appropriate exception.
                            throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx),  null );
                        }
                        
                        if ( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 )
                        {
                            // We need to create an EnlistmentNotifyShim if native threads are not allowed to enter managed code.
                            handlePhase0 = HandleTable.AllocHandle( enlistment );

                            RuntimeHelpers.PrepareConstrainedRegions();
                            try { }
                            finally
                            {
                                oletxTransaction.RealTransaction.TransactionShim.Phase0Enlist(
                                    handlePhase0,
                                    out phase0Shim );
                                phase0EnlistSucceeded = true;
                            }
                            enlistment.Phase0EnlistmentShim = phase0Shim;
                        }

                        enlistment.phase1Handle = HandleTable.AllocHandle( enlistment );
                        localResourceManagerShim.Enlist(
                            oletxTransaction.RealTransaction.TransactionShim,
                            enlistment.phase1Handle,
                            out enlistmentShim );

                        enlistment.EnlistmentShim = enlistmentShim;
                    }
                    catch (COMException comException)
                    {
                        // There is no string mapping for XACT_E_TOOMANY_ENLISTMENTS, so we need to do it here.
                        if ( NativeMethods.XACT_E_TOOMANY_ENLISTMENTS == comException.ErrorCode )
                        {
                            throw TransactionException.Create(
                                SR.GetString( SR.TraceSourceOletx ),
                                SR.GetString( SR.OletxTooManyEnlistments ),
                                comException );
                        }

                        OletxTransactionManager.ProxyException( comException );

                        throw;
                    }
                    finally
                    {
                        if ( enlistment.EnlistmentShim == null )
                        {
                            // If the enlistment shim was never assigned then something blew up.
                            // Perform some cleanup.
                            if ( handlePhase0 != IntPtr.Zero && !phase0EnlistSucceeded )
                            {
                                // Only clean up the phase0 handle if the phase 0 enlistment did not succeed.
                                // This is because the notification processing code expects it to exist.
                                HandleTable.FreeHandle( handlePhase0 );
                            }

                            if ( enlistment.phase1Handle != IntPtr.Zero )
                            {
                                HandleTable.FreeHandle( enlistment.phase1Handle );
                            }

                            // Note this code used to call unenlist however this allows race conditions where
                            // it is unclear if the handlePhase0 should be freed or not.  The notification
                            // thread should get a phase0Request and it will free the Handle at that point.
                        }
                    }
                }

                enlistmentSucceeded = true;
            }
            finally
            {
                if ( !enlistmentSucceeded &&
                    ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0) && 
                    undecidedEnlistmentsIncremented )
                {
                    oletxTransaction.RealTransaction.DecrementUndecidedEnlistments();
                }
            }

            return enlistment;
        }
Пример #31
0
        internal IPromotedEnlistment CommonEnlistVolatile(
            IEnlistmentNotificationInternal enlistmentNotification,
            EnlistmentOptions enlistmentOptions,
            OletxTransaction oletxTransaction
            )
        {
            OletxVolatileEnlistment enlistment = null;
            bool needVoterEnlistment = false;
            bool needPhase0Enlistment = false;
            OletxPhase0VolatileEnlistmentContainer localPhase0VolatileContainer = null;
            OletxPhase1VolatileEnlistmentContainer localPhase1VolatileContainer = null;
            IntPtr phase0Handle = IntPtr.Zero;
            IVoterBallotShim voterShim = null;
            IPhase0EnlistmentShim phase0Shim = null;
            bool enlistmentSucceeded = false;

            // Yes, we are talking to the proxy while holding the lock on the RealOletxTransaction.
            // If we don't then things get real sticky with other threads allocating containers.
            // We only do this the first time we get a depenent clone of a given type (delay vs. non-delay).
            // After that, we don't create a new container, except for Phase0 if we need to create one
            // for a second wave.
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                lock ( this )
                {
                    enlistment = new OletxVolatileEnlistment(
                        enlistmentNotification,
                        enlistmentOptions,
                        oletxTransaction
                        );

                    if ( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 )
                    {
                        if ( null == this.phase0EnlistVolatilementContainerList )
                        {
                            // Not using a MemoryBarrier because all access to this member variable is done when holding
                            // a lock on the object.
                            this.phase0EnlistVolatilementContainerList = new ArrayList(1);
                        }
                        // We may have failed the proxy enlistment for the first container, but we would have
                        // allocated the list.  That is why we have this check here.
                        if ( 0 == this.phase0EnlistVolatilementContainerList.Count )
                        {
                            localPhase0VolatileContainer = new OletxPhase0VolatileEnlistmentContainer( this );
                            needPhase0Enlistment = true;
                        }
                        else
                        {
                            localPhase0VolatileContainer = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer;
                            if ( ! localPhase0VolatileContainer.NewEnlistmentsAllowed )
                            {
                                localPhase0VolatileContainer = new OletxPhase0VolatileEnlistmentContainer( this );
                                needPhase0Enlistment = true;
                            }
                            else
                            {
                                needPhase0Enlistment = false;
                            }
                        }

                        if ( needPhase0Enlistment )
                        {
                            // We need to create a VoterNotifyShim if native threads are not allowed to enter managed code.
                            phase0Handle = HandleTable.AllocHandle( localPhase0VolatileContainer );
                        }
                    }
                    else  // not EDPR = TRUE - may need a voter... 
                    {
                        if ( null == this.phase1EnlistVolatilementContainer )
                        {
                            needVoterEnlistment = true;
                            localPhase1VolatileContainer = new OletxPhase1VolatileEnlistmentContainer( this );

                            // We need to create a VoterNotifyShim.
                            localPhase1VolatileContainer.voterHandle = 
                                HandleTable.AllocHandle( localPhase1VolatileContainer );
                        }
                        else
                        {
                            needVoterEnlistment = false;
                            localPhase1VolatileContainer = this.phase1EnlistVolatilementContainer;
                        }
                    }


                    try
                    {
                        // If enlistDuringPrepareRequired is true, we need to ask the proxy to create a Phase0 enlistment.
                        if ( needPhase0Enlistment )
                        {
                            lock ( localPhase0VolatileContainer )
                            {
                                transactionShim.Phase0Enlist(
                                    phase0Handle,
                                    out phase0Shim );

                                localPhase0VolatileContainer.Phase0EnlistmentShim = phase0Shim;
                            }

                        }

                        if ( needVoterEnlistment )
                        {
                            this.transactionShim.CreateVoter(
                                localPhase1VolatileContainer.voterHandle,
                                out voterShim );

                            enlistmentSucceeded = true;
                            localPhase1VolatileContainer.VoterBallotShim = voterShim;
                        }
                
                        if ( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 )
                        {
                            localPhase0VolatileContainer.AddEnlistment(
                                enlistment
                                );
                            if ( needPhase0Enlistment )
                            {
                                this.phase0EnlistVolatilementContainerList.Add( localPhase0VolatileContainer );
                            }
                        }
                        else
                        {
                            localPhase1VolatileContainer.AddEnlistment(
                                enlistment
                                );

                            if ( needVoterEnlistment )
                            {
                                Debug.Assert( ( null == this.phase1EnlistVolatilementContainer ),
                                    "RealOletxTransaction.CommonEnlistVolatile - phase1VolContainer not null when expected." );
                                this.phase1EnlistVolatilementContainer = localPhase1VolatileContainer;
                            }
                        }
                    }
                    catch (COMException comException)
                    {
                        OletxTransactionManager.ProxyException( comException );
                        throw;
                    }
                }
            }
            finally
            {
                if ( phase0Handle != IntPtr.Zero && localPhase0VolatileContainer.Phase0EnlistmentShim == null )
                {
                    HandleTable.FreeHandle( phase0Handle );
                }

                if ( !enlistmentSucceeded && 
                    null != localPhase1VolatileContainer && 
                    localPhase1VolatileContainer.voterHandle != IntPtr.Zero &&
                    needVoterEnlistment )
                {
                    HandleTable.FreeHandle( localPhase1VolatileContainer.voterHandle );
                }
            }

            return enlistment;
        }
 internal static Transaction FindOrCreatePromotedTransaction(Guid transactionIdentifier, OletxTransaction oletx)
 {
     Transaction target = null;
     Hashtable promotedTransactionTable = PromotedTransactionTable;
     lock (promotedTransactionTable)
     {
         WeakReference reference = (WeakReference) promotedTransactionTable[transactionIdentifier];
         if (reference != null)
         {
             target = reference.Target as Transaction;
             if (null != target)
             {
                 oletx.Dispose();
                 return target.InternalClone();
             }
             lock (promotedTransactionTable)
             {
                 promotedTransactionTable.Remove(transactionIdentifier);
             }
         }
         target = new Transaction(oletx) {
             internalTransaction = { finalizedObject = new FinalizedObject(target.internalTransaction, oletx.Identifier) }
         };
         reference = new WeakReference(target, false);
         promotedTransactionTable[oletx.Identifier] = reference;
     }
     oletx.savedLtmPromotedTransaction = target;
     FireDistributedTransactionStarted(target);
     return target;
 }