示例#1
0
        internal void ReenlistThread(object state)
        {
            int                  count               = 0;
            bool                 flag                = false;
            OletxEnlistment      enlistment          = null;
            IResourceManagerShim resourceManagerShim = null;
            Timer                reenlistThreadTimer = null;
            bool                 flag2               = false;
            OletxResourceManager manager             = (OletxResourceManager)state;

            try
            {
                if (DiagnosticTrace.Information)
                {
                    MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxResourceManager.ReenlistThread");
                }
                lock (manager)
                {
                    resourceManagerShim         = manager.ResourceManagerShim;
                    reenlistThreadTimer         = manager.reenlistThreadTimer;
                    manager.reenlistThreadTimer = null;
                    manager.reenlistThread      = Thread.CurrentThread;
                }
                if (resourceManagerShim != null)
                {
                    lock (manager.reenlistList)
                    {
                        count = manager.reenlistList.Count;
                    }
                    flag = false;
                    while ((!flag && (count > 0)) && (resourceManagerShim != null))
                    {
                        lock (manager.reenlistList)
                        {
                            enlistment = null;
                            count--;
                            if (manager.reenlistList.Count == 0)
                            {
                                flag = true;
                            }
                            else
                            {
                                enlistment = manager.reenlistList[0] as OletxEnlistment;
                                if (enlistment == null)
                                {
                                    if (DiagnosticTrace.Critical)
                                    {
                                        InternalErrorTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "");
                                    }
                                    throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("InternalError"), null);
                                }
                                manager.reenlistList.RemoveAt(0);
                                object obj7 = enlistment;
                                lock (obj7)
                                {
                                    if (OletxEnlistment.OletxEnlistmentState.Done == enlistment.State)
                                    {
                                        enlistment = null;
                                    }
                                    else if (OletxEnlistment.OletxEnlistmentState.Prepared != enlistment.State)
                                    {
                                        manager.reenlistList.Add(enlistment);
                                        enlistment = null;
                                    }
                                }
                            }
                        }
                        if (enlistment != null)
                        {
                            OletxTransactionOutcome notKnownYet = OletxTransactionOutcome.NotKnownYet;
                            try
                            {
                                if (enlistment.ProxyPrepareInfoByteArray == null)
                                {
                                    if (DiagnosticTrace.Critical)
                                    {
                                        InternalErrorTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "");
                                    }
                                    throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("InternalError"), null);
                                }
                                resourceManagerShim.Reenlist((uint)enlistment.ProxyPrepareInfoByteArray.Length, enlistment.ProxyPrepareInfoByteArray, out notKnownYet);
                                if (notKnownYet == OletxTransactionOutcome.NotKnownYet)
                                {
                                    object obj5 = enlistment;
                                    lock (obj5)
                                    {
                                        if (OletxEnlistment.OletxEnlistmentState.Done == enlistment.State)
                                        {
                                            enlistment = null;
                                        }
                                        else
                                        {
                                            lock (manager.reenlistList)
                                            {
                                                manager.reenlistList.Add(enlistment);
                                                enlistment = null;
                                            }
                                        }
                                    }
                                }
                            }
                            catch (COMException exception)
                            {
                                if (System.Transactions.Oletx.NativeMethods.XACT_E_CONNECTION_DOWN != exception.ErrorCode)
                                {
                                    throw;
                                }
                                if (DiagnosticTrace.Verbose)
                                {
                                    ExceptionConsumedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), exception);
                                }
                                if (System.Transactions.Oletx.NativeMethods.XACT_E_CONNECTION_DOWN == exception.ErrorCode)
                                {
                                    manager.ResourceManagerShim = null;
                                    resourceManagerShim         = manager.ResourceManagerShim;
                                }
                            }
                            if (enlistment != null)
                            {
                                object obj3 = enlistment;
                                lock (obj3)
                                {
                                    if (OletxEnlistment.OletxEnlistmentState.Done != enlistment.State)
                                    {
                                        lock (manager.reenlistList)
                                        {
                                            manager.reenlistPendingList.Add(enlistment);
                                        }
                                        if (OletxTransactionOutcome.Committed != notKnownYet)
                                        {
                                            if (OletxTransactionOutcome.Aborted != notKnownYet)
                                            {
                                                if (DiagnosticTrace.Critical)
                                                {
                                                    InternalErrorTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "");
                                                }
                                                throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("InternalError"), null);
                                            }
                                            enlistment.State = OletxEnlistment.OletxEnlistmentState.Aborting;
                                            if (DiagnosticTrace.Verbose)
                                            {
                                                EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), enlistment.EnlistmentTraceId, NotificationCall.Rollback);
                                            }
                                            enlistment.EnlistmentNotification.Rollback(enlistment);
                                        }
                                        else
                                        {
                                            enlistment.State = OletxEnlistment.OletxEnlistmentState.Committing;
                                            if (DiagnosticTrace.Verbose)
                                            {
                                                EnlistmentNotificationCallTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), enlistment.EnlistmentTraceId, NotificationCall.Commit);
                                            }
                                            enlistment.EnlistmentNotification.Commit(enlistment);
                                        }
                                    }
                                    else
                                    {
                                        enlistment = null;
                                    }
                                    continue;
                                }
                            }
                        }
                    }
                }
                resourceManagerShim = null;
                lock (manager.reenlistList)
                {
                    lock (manager)
                    {
                        count = manager.reenlistList.Count;
                        if ((0 >= count) && (0 >= manager.reenlistPendingList.Count))
                        {
                            if (!manager.CallProxyReenlistComplete())
                            {
                                manager.reenlistThreadTimer = reenlistThreadTimer;
                                if (!reenlistThreadTimer.Change(0x2710, -1))
                                {
                                    throw TransactionException.CreateInvalidOperationException(System.Transactions.SR.GetString("TraceSourceLtm"), System.Transactions.SR.GetString("UnexpectedTimerFailure"), null);
                                }
                            }
                            else
                            {
                                flag2 = true;
                            }
                        }
                        else
                        {
                            manager.reenlistThreadTimer = reenlistThreadTimer;
                            if (!reenlistThreadTimer.Change(0x2710, -1))
                            {
                                throw TransactionException.CreateInvalidOperationException(System.Transactions.SR.GetString("TraceSourceLtm"), System.Transactions.SR.GetString("UnexpectedTimerFailure"), null);
                            }
                        }
                        manager.reenlistThread = null;
                    }
                    if (DiagnosticTrace.Information)
                    {
                        MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxResourceManager.ReenlistThread");
                    }
                }
            }
            finally
            {
                resourceManagerShim = null;
                if (flag2 && (reenlistThreadTimer != null))
                {
                    reenlistThreadTimer.Dispose();
                }
            }
        }
示例#2
0
    internal void ReenlistThread(object?state)
    {
        int                 localLoopCount;
        bool                done;
        OletxEnlistment?    localEnlistment;
        ResourceManagerShim?localResourceManagerShim;
        bool                success;
        Timer?              localTimer        = null;
        bool                disposeLocalTimer = false;

        OletxResourceManager resourceManager = (OletxResourceManager)state !;

        try
        {
            TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;
            if (etwLog.IsEnabled())
            {
                etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, this, $"{nameof(OletxResourceManager)}.{nameof(ReenlistThread)}");
            }

            lock (resourceManager)
            {
                localResourceManagerShim = resourceManager.ResourceManagerShim;
                localTimer = resourceManager.ReenlistThreadTimer;
                resourceManager.ReenlistThreadTimer = null;
                resourceManager.reenlistThread      = Thread.CurrentThread;
            }

            // We only want to do work if we have a resourceManagerShim.
            if (localResourceManagerShim != null)
            {
                lock (resourceManager.ReenlistList)
                {
                    // Get the current count on the list.
                    localLoopCount = resourceManager.ReenlistList.Count;
                }

                done = false;
                while (!done && localLoopCount > 0 && localResourceManagerShim != null)
                {
                    lock (resourceManager.ReenlistList)
                    {
                        localEnlistment = null;
                        localLoopCount--;
                        if (resourceManager.ReenlistList.Count == 0)
                        {
                            done = true;
                        }
                        else
                        {
                            localEnlistment = resourceManager.ReenlistList[0] as OletxEnlistment;
                            if (localEnlistment == null)
                            {
                                if (etwLog.IsEnabled())
                                {
                                    etwLog.InternalError();
                                }

                                throw TransactionException.Create(SR.InternalError, null);
                            }

                            resourceManager.ReenlistList.RemoveAt(0);
                            object syncRoot = localEnlistment;
                            lock (syncRoot)
                            {
                                if (OletxEnlistment.OletxEnlistmentState.Done == localEnlistment.State)
                                {
                                    // We may be racing with a RecoveryComplete here.  Just forget about this
                                    // enlistment.
                                    localEnlistment = null;
                                }

                                else if (OletxEnlistment.OletxEnlistmentState.Prepared != localEnlistment.State)
                                {
                                    // The app hasn't yet responded to Prepare, so we don't know
                                    // if it is indoubt or not yet.  So just re-add it to the end
                                    // of the list.
                                    resourceManager.ReenlistList.Add(localEnlistment);
                                    localEnlistment = null;
                                }
                            }
                        }
                    }

                    if (localEnlistment != null)
                    {
                        OletxTransactionOutcome localOutcome = OletxTransactionOutcome.NotKnownYet;
                        try
                        {
                            Debug.Assert(localResourceManagerShim != null, "ReenlistThread - localResourceManagerShim is null");

                            // Make sure we have a prepare info.
                            if (localEnlistment.ProxyPrepareInfoByteArray == null)
                            {
                                Debug.Assert(false, string.Format(null, "this.prepareInfoByteArray == null in RecoveryInformation()"));
                                if (etwLog.IsEnabled())
                                {
                                    etwLog.InternalError();
                                }

                                throw TransactionException.Create(SR.InternalError, null);
                            }

                            localResourceManagerShim.Reenlist(localEnlistment.ProxyPrepareInfoByteArray, out localOutcome);

                            if (localOutcome == OletxTransactionOutcome.NotKnownYet)
                            {
                                object syncRoot = localEnlistment;
                                lock (syncRoot)
                                {
                                    if (OletxEnlistment.OletxEnlistmentState.Done == localEnlistment.State)
                                    {
                                        // We may be racing with a RecoveryComplete here.  Just forget about this
                                        // enlistment.
                                        localEnlistment = null;
                                    }
                                    else
                                    {
                                        // Put the enlistment back on the end of the list for retry later.
                                        lock (resourceManager.ReenlistList)
                                        {
                                            resourceManager.ReenlistList.Add(localEnlistment);
                                            localEnlistment = null;
                                        }
                                    }
                                }
                            }
                        }
                        catch (COMException ex) when(ex.ErrorCode == OletxHelper.XACT_E_CONNECTION_DOWN)
                        {
                            if (etwLog.IsEnabled())
                            {
                                etwLog.ExceptionConsumed(TraceSourceType.TraceSourceOleTx, ex);
                            }

                            // Release the resource manager so we can create a new one.
                            resourceManager.ResourceManagerShim = null;

                            // Now create a new resource manager with the proxy.
                            localResourceManagerShim = resourceManager.ResourceManagerShim;
                        }

                        // If we get here and we still have localEnlistment, then we got the outcome.
                        if (localEnlistment != null)
                        {
                            object syncRoot = localEnlistment;
                            lock (syncRoot)
                            {
                                if (OletxEnlistment.OletxEnlistmentState.Done == localEnlistment.State)
                                {
                                    // We may be racing with a RecoveryComplete here.  Just forget about this
                                    // enlistment.
                                    localEnlistment = null;
                                }
                                else
                                {
                                    // We are going to send the notification to the RM.  We need to put the
                                    // enlistment on the reenlistPendingList.  We lock the reenlistList because
                                    // we have decided that is the lock that protects both lists.  The entry will
                                    // be taken off the reenlistPendingList when the enlistment has
                                    // EnlistmentDone called on it.  The enlistment will call
                                    // RemoveFromReenlistPending.
                                    lock (resourceManager.ReenlistList)
                                    {
                                        resourceManager.ReenlistPendingList.Add(localEnlistment);
                                    }

                                    if (localOutcome == OletxTransactionOutcome.Committed)
                                    {
                                        localEnlistment.State = OletxEnlistment.OletxEnlistmentState.Committing;

                                        if (etwLog.IsEnabled())
                                        {
                                            etwLog.EnlistmentStatus(TraceSourceType.TraceSourceOleTx, localEnlistment.EnlistmentTraceId, NotificationCall.Commit);
                                        }

                                        localEnlistment.EnlistmentNotification !.Commit(localEnlistment);
                                    }
                                    else if (localOutcome == OletxTransactionOutcome.Aborted)
                                    {
                                        localEnlistment.State = OletxEnlistment.OletxEnlistmentState.Aborting;

                                        if (etwLog.IsEnabled())
                                        {
                                            etwLog.EnlistmentStatus(TraceSourceType.TraceSourceOleTx, localEnlistment.EnlistmentTraceId, NotificationCall.Rollback);
                                        }

                                        localEnlistment.EnlistmentNotification !.Rollback(localEnlistment);
                                    }
                                    else
                                    {
                                        if (etwLog.IsEnabled())
                                        {
                                            etwLog.InternalError();
                                        }

                                        throw TransactionException.Create(SR.InternalError, null);
                                    }
                                }
                            }
                        } // end of if null != localEnlistment
                    }     // end of if null != localEnlistment
                }
            }

            localResourceManagerShim = null;

            // Check to see if there is more work to do.
            lock (resourceManager.ReenlistList)
            {
                lock (resourceManager)
                {
                    // Get the current count on the list.
                    localLoopCount = resourceManager.ReenlistList.Count;
                    if (localLoopCount <= 0 && resourceManager.ReenlistPendingList.Count <= 0)
                    {
                        // No more entries on the list.  Try calling ReenlistComplete on the proxy, if
                        // appropriate.
                        // If the application has called RecoveryComplete,
                        // we are responsible for calling ReenlistComplete on the
                        // proxy.
                        success = resourceManager.CallProxyReenlistComplete();
                        if (success)
                        {
                            // Okay, the reenlist thread is done and we don't need to schedule another one.
                            disposeLocalTimer = true;
                        }
                        else
                        {
                            // We couldn't talk to the proxy to do ReenlistComplete, so schedule
                            // the thread again for 10 seconds from now.
                            resourceManager.ReenlistThreadTimer = localTimer;
                            if (!localTimer !.Change(10000, Timeout.Infinite))
                            {
                                throw TransactionException.CreateInvalidOperationException(
                                          TraceSourceType.TraceSourceLtm,
                                          SR.UnexpectedTimerFailure,
                                          null);
                            }
                        }
                    }
                    else
                    {
                        // There are still entries on the list, so they must not be
                        // resovled, yet.  Schedule the thread again in 10 seconds.
                        resourceManager.ReenlistThreadTimer = localTimer;
                        if (!localTimer !.Change(10000, Timeout.Infinite))
                        {
                            throw TransactionException.CreateInvalidOperationException(
                                      TraceSourceType.TraceSourceLtm,
                                      SR.UnexpectedTimerFailure,
                                      null);
                        }
                    }

                    resourceManager.reenlistThread = null;
                }

                if (etwLog.IsEnabled())
                {
                    etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, this, $"{nameof(OletxResourceManager)}.{nameof(ReenlistThread)}");
                }
            }
        }  // end of outer-most try
        finally
        {
            localResourceManagerShim = null;
            if (disposeLocalTimer && localTimer != null)
            {
                localTimer.Dispose();
            }
        }
    }  // end of ReenlistThread method;
示例#3
0
        internal OletxEnlistment Reenlist(int prepareInfoLength, byte[] prepareInfo, IEnlistmentNotificationInternal enlistmentNotification)
        {
            OletxRecoveryInformation information;
            OletxTransactionOutcome  notKnownYet         = OletxTransactionOutcome.NotKnownYet;
            OletxTransactionStatus   xactStatus          = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_NONE;
            MemoryStream             serializationStream = new MemoryStream(prepareInfo);
            IFormatter formatter = new BinaryFormatter();

            try
            {
                information = formatter.Deserialize(serializationStream) as OletxRecoveryInformation;
            }
            catch (SerializationException exception2)
            {
                throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "prepareInfo", exception2);
            }
            if (information == null)
            {
                throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "prepareInfo");
            }
            byte[] b = new byte[0x10];
            for (int i = 0; i < 0x10; i++)
            {
                b[i] = information.proxyRecoveryInformation[i + 0x10];
            }
            Guid guid = new Guid(b);

            if (guid != this.resourceManagerIdentifier)
            {
                throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("ResourceManagerIdDoesNotMatchRecoveryInformation"), null);
            }
            IResourceManagerShim resourceManagerShim = null;

            try
            {
                resourceManagerShim = this.ResourceManagerShim;
                if (resourceManagerShim == null)
                {
                    throw new COMException(System.Transactions.SR.GetString("DtcTransactionManagerUnavailable"), System.Transactions.Oletx.NativeMethods.XACT_E_CONNECTION_DOWN);
                }
                resourceManagerShim.Reenlist(Convert.ToUInt32(information.proxyRecoveryInformation.Length, CultureInfo.InvariantCulture), information.proxyRecoveryInformation, out notKnownYet);
                if (OletxTransactionOutcome.Committed == notKnownYet)
                {
                    xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_COMMITTED;
                }
                else if (OletxTransactionOutcome.Aborted == notKnownYet)
                {
                    xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_ABORTED;
                }
                else
                {
                    xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED;
                    this.StartReenlistThread();
                }
            }
            catch (COMException exception)
            {
                if (System.Transactions.Oletx.NativeMethods.XACT_E_CONNECTION_DOWN != exception.ErrorCode)
                {
                    throw;
                }
                xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED;
                this.ResourceManagerShim = null;
                this.StartReenlistThread();
                if (DiagnosticTrace.Verbose)
                {
                    ExceptionConsumedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), exception);
                }
            }
            finally
            {
                resourceManagerShim = null;
            }
            return(new OletxEnlistment(enlistmentNotification, xactStatus, information.proxyRecoveryInformation, this));
        }
示例#4
0
    internal OletxEnlistment Reenlist(byte[] prepareInfo, IEnlistmentNotificationInternal enlistmentNotification)
    {
        OletxTransactionOutcome outcome    = OletxTransactionOutcome.NotKnownYet;
        OletxTransactionStatus  xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_NONE;

        if (prepareInfo == null)
        {
            throw new ArgumentException(SR.InvalidArgument, nameof(prepareInfo));
        }

        // Verify that the resource manager guid in the recovery info matches that of the calling resource manager.
        byte[] rmGuidArray = new byte[16];
        for (int i = 0; i < 16; i++)
        {
            rmGuidArray[i] = prepareInfo[i + 16];
        }
        Guid rmGuid = new(rmGuidArray);

        if (rmGuid != ResourceManagerIdentifier)
        {
            throw TransactionException.Create(TraceSourceType.TraceSourceOleTx, SR.ResourceManagerIdDoesNotMatchRecoveryInformation, null);
        }

        // Ask the proxy resource manager to reenlist.
        ResourceManagerShim?localResourceManagerShim = null;

        try
        {
            localResourceManagerShim = ResourceManagerShim;
            if (localResourceManagerShim == null)
            {
                // The TM must be down.  Throw the exception that will get caught below and will cause
                // the enlistment to start the ReenlistThread.  The TMDown thread will be trying to reestablish
                // connection with the TM and will start the reenlist thread when it does.
                throw new COMException(SR.DtcTransactionManagerUnavailable, OletxHelper.XACT_E_CONNECTION_DOWN);
            }

            // Only wait for 5 milliseconds.  If the TM doesn't have the outcome now, we will
            // put the enlistment on the reenlistList for later processing.
            localResourceManagerShim.Reenlist(prepareInfo, out outcome);

            if (OletxTransactionOutcome.Committed == outcome)
            {
                xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_COMMITTED;
            }
            else if (OletxTransactionOutcome.Aborted == outcome)
            {
                xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_ABORTED;
            }
            else  // we must not know the outcome yet.
            {
                xactStatus = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED;
                StartReenlistThread();
            }
        }
        catch (COMException ex) when(ex.ErrorCode == OletxHelper.XACT_E_CONNECTION_DOWN)
        {
            xactStatus          = OletxTransactionStatus.OLETX_TRANSACTION_STATUS_PREPARED;
            ResourceManagerShim = null;
            StartReenlistThread();

            TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;

            if (etwLog.IsEnabled())
            {
                etwLog.ExceptionConsumed(TraceSourceType.TraceSourceOleTx, ex);
            }
        }
        finally
        {
            localResourceManagerShim = null;
        }

        // Now create our enlistment to tell the client the outcome.
        return(new OletxEnlistment(enlistmentNotification, xactStatus, prepareInfo, this));
    }