private TransactionException CreateVolatileEnlistment(System.Transactions.Transaction transactionToEnlist) { TransactionException exception = null; PersistenceContextEnlistment enlistment = null; int hashCode = transactionToEnlist.GetHashCode(); lock (System.ServiceModel.Activities.Dispatcher.PersistenceContext.Enlistments) { try { if (!System.ServiceModel.Activities.Dispatcher.PersistenceContext.Enlistments.TryGetValue(hashCode, out enlistment)) { enlistment = new PersistenceContextEnlistment(this.PersistenceContext, transactionToEnlist); transactionToEnlist.EnlistVolatile(enlistment, EnlistmentOptions.None); System.ServiceModel.Activities.Dispatcher.PersistenceContext.Enlistments.Add(hashCode, enlistment); return(exception); } enlistment.AddToEnlistment(this.PersistenceContext); return(exception); } catch (TransactionException exception2) { exception = exception2; this.PersistenceContext.ScheduleNextTransactionWaiter(); } } return(exception); }
internal static void DoPrepare(object state) { PersistenceContextEnlistment enlistment = state as PersistenceContextEnlistment; lock (enlistment.ThisLock) { enlistment.tooLateForMoreUndo = true; } enlistment.preparingEnlistment.Prepared(); }
internal static void DoPrepare(object state) { PersistenceContextEnlistment pcEnlist = state as PersistenceContextEnlistment; Fx.Assert(null != pcEnlist, "PersistenceContextEnlistment.DoPrepare called with an object that is not a PersistenceContext."); lock (pcEnlist.ThisLock) { pcEnlist.tooLateForMoreUndo = true; } // This needs to be done outside of the lock because it could induce System.Transactions // to do a whole bunch of other work inline, including issuing the Commit call and doing // Completion notifications for hte transaction. We don't want to be holding the lock // during all of that. pcEnlist.preparingEnlistment.Prepared(); }
internal static void DoCommit(object state) { PersistenceContextEnlistment enlistment = state as PersistenceContextEnlistment; lock (enlistment.ThisLock) { foreach (PersistenceContext context in enlistment.enlistedContexts) { context.ScheduleNextTransactionWaiter(); } } lock (PersistenceContext.Enlistments) { PersistenceContext.Enlistments.Remove(enlistment.transaction.GetHashCode()); } enlistment.enlistment.Done(); }
internal static void DoRollback(object state) { PersistenceContextEnlistment enlistment = state as PersistenceContextEnlistment; lock (enlistment.ThisLock) { enlistment.tooLateForMoreUndo = true; foreach (PersistenceContext context in enlistment.enlistedContexts) { context.Abort(); context.ScheduleNextTransactionWaiter(); } } lock (PersistenceContext.Enlistments) { PersistenceContext.Enlistments.Remove(enlistment.transaction.GetHashCode()); } enlistment.enlistment.Done(); }
internal static void DoCommit(object state) { PersistenceContextEnlistment pcEnlist = state as PersistenceContextEnlistment; Fx.Assert(null != pcEnlist, "PersistenceContextEnlistment.DoCommit called with an object that is not a PersistenceContext."); lock (pcEnlist.ThisLock) { // Wake up the next waiter for the pc, if any. foreach (PersistenceContext context in pcEnlist.enlistedContexts) { context.ScheduleNextTransactionWaiter(); } } lock (PersistenceContext.Enlistments) { PersistenceContext.Enlistments.Remove(pcEnlist.transaction.GetHashCode()); } // This needs to be outside the lock because SysTx might do other stuff on the thread. pcEnlist.enlistment.Done(); }
internal static void DoIndoubt(object state) { PersistenceContextEnlistment pcEnlist = state as PersistenceContextEnlistment; Fx.Assert(null != pcEnlist, "PersistenceContextEnlistment.DoIndoubt called with an object that is not a PersistenceContext."); lock (pcEnlist.ThisLock) { pcEnlist.tooLateForMoreUndo = true; foreach (PersistenceContext context in pcEnlist.enlistedContexts) { context.Abort(); context.ScheduleNextTransactionWaiter(); } } lock (PersistenceContext.Enlistments) { PersistenceContext.Enlistments.Remove(pcEnlist.transaction.GetHashCode()); } // This needs to be outside the lock because SysTx might do other stuff on the thread. pcEnlist.enlistment.Done(); }
TransactionException CreateVolatileEnlistment(Transaction transactionToEnlist) { TransactionException result = null; PersistenceContextEnlistment enlistment = null; int key = transactionToEnlist.GetHashCode(); lock (PersistenceContext.Enlistments) { try { if (!PersistenceContext.Enlistments.TryGetValue(key, out enlistment)) { enlistment = new PersistenceContextEnlistment(this.PersistenceContext, transactionToEnlist); transactionToEnlist.EnlistVolatile(enlistment, EnlistmentOptions.None); // We don't save of the Enlistment object returned from EnlistVolatile. We don't need // it here. When our PersistenceContextEnlistment object gets notified on Prepare, // Commit, Rollback, or InDoubt, it is provided with the Enlistment object. PersistenceContext.Enlistments.Add(key, enlistment); } else { enlistment.AddToEnlistment(this.PersistenceContext); } } catch (TransactionException txException) { result = txException; // We own the lock but failed to create enlistment. Manually wake up the next waiter. // We only handle TransactionException, in case of other exception that failed to create enlistment, // It will fallback to Timeout. This is safe to avoid multiple waiters owning same lock. this.PersistenceContext.ScheduleNextTransactionWaiter(); } } return(result); }
TransactionException CreateVolatileEnlistment(Transaction transactionToEnlist) { TransactionException result = null; PersistenceContextEnlistment enlistment = null; int key = transactionToEnlist.GetHashCode(); lock (PersistenceContext.Enlistments) { try { if (!PersistenceContext.Enlistments.TryGetValue(key, out enlistment)) { enlistment = new PersistenceContextEnlistment(this.PersistenceContext, transactionToEnlist); transactionToEnlist.EnlistVolatile(enlistment, EnlistmentOptions.None); // We don't save of the Enlistment object returned from EnlistVolatile. We don't need // it here. When our PersistenceContextEnlistment object gets notified on Prepare, // Commit, Rollback, or InDoubt, it is provided with the Enlistment object. PersistenceContext.Enlistments.Add(key, enlistment); } else { enlistment.AddToEnlistment(this.PersistenceContext); } } catch (TransactionException txException) { result = txException; // We own the lock but failed to create enlistment. Manually wake up the next waiter. // We only handle TransactionException, in case of other exception that failed to create enlistment, // It will fallback to Timeout. This is safe to avoid multiple waiters owning same lock. this.PersistenceContext.ScheduleNextTransactionWaiter(); } } return result; }