/// <summary> /// <see cref="IEnlistmentNotification.Prepare(PreparingEnlistment)"/> /// </summary> /// <param name="preparingEnlistment"> /// PreparingEnlistment /// </param> public void Prepare(PreparingEnlistment preparingEnlistment) { bool prepared = false; try { // notify subscribers; if an exception is thrown preparation fails and transaction cannot be committed NotifyPrepare(); prepared = true; } catch (StorageTransactionException e) { _log.ErrorFormat("Master initiated prepare failed: {0}", e); } finally { if (prepared) { // the sequence will be: // this.Prepared begin // this.Commit begin // this.Commit end // this.Prepared end preparingEnlistment.Prepared(); } else { preparingEnlistment.ForceRollback(); // experiment shows that Rollback will not be invoked (at least on volatile resource), so have to notify here NotifyCompletion(false); } } }
public void Prepare(PreparingEnlistment preparingEnlistment) { Logger.TheInstance.WriteToLog("VolatileRM: Prepare"); DoPrepare(); preparingEnlistment.Prepared(); }
public virtual void Prepare(PreparingEnlistment preparingEnlistment) { Trace.WriteIf(Tracing.Is.TraceVerbose, string.Empty); if (null == preparingEnlistment) { return; } try { Operation.Info = Convert.ToBase64String(preparingEnlistment.RecoveryInformation()); if (ConfigureOperation() && Operation.Do()) { Trace.WriteIf(Tracing.Is.TraceVerbose, "preparingEnlistment.Prepared()"); preparingEnlistment.Prepared(); return; } Trace.WriteIf(Tracing.Is.TraceVerbose, "preparingEnlistment.ForceRollback()"); preparingEnlistment.ForceRollback(); } catch (Exception exception) { Trace.TraceError("{0}", exception); preparingEnlistment.ForceRollback(exception); } }
void OnPrepare(PreparingEnlistment preparingEnlistment) { bool prepareNeeded = false; lock (ThisLock) { if (TooLateToEnlist) { // Skip this if somehow we already got rolled back or committed. return; } TooLateToEnlist = true; if (OperationPending && AcquirePending == null) { Fx.Assert(CurrentExecutionContext != null, "Should either be acquiring or executing in Prepare."); this.pendingPreparingEnlistment = preparingEnlistment; } else { prepareNeeded = true; } } if (prepareNeeded) { preparingEnlistment.Prepared(); } }
private void OnPrepare(PreparingEnlistment preparingEnlistment) { bool flag = false; lock (this.ThisLock) { if (this.TooLateToEnlist) { return; } this.TooLateToEnlist = true; if (this.OperationPending && (this.AcquirePending == null)) { this.pendingPreparingEnlistment = preparingEnlistment; } else { flag = true; } } if (flag) { preparingEnlistment.Prepared(); } }
private static void HandleEndPrepare(IAsyncResult result) { PreparingEnlistment asyncState = (PreparingEnlistment)result.AsyncState; bool flag = false; try { if (!result.CompletedSynchronously) { PrepareAsyncResult.End(result); asyncState.Prepared(); } flag = true; } catch (TransactionException) { } finally { if (!flag) { asyncState.ForceRollback(); } } }
public void Prepare(PreparingEnlistment preparingEnlistment) { try { log.Debug("Prepare {0}, Messages {1}. Sending the message batch.", TransactionId, Messages.Count); if (_onprepare != null) { _onprepare(this); } preparingEnlistment.Prepared(); } catch (Exception ex) { log.Error("Error preparing transaction {0} ({1} messages): {2}", TransactionId, Messages.Count, ex); preparingEnlistment.ForceRollback(ex); TransactionOpen = false; if (_onrollback != null) { try { _onrollback(this); } catch (Exception e2) { log.Error("Error performing rollback after a failed prepare: {0}", e2); } } } }
/// <summary> /// Notifies an enlisted object that a transaction is being prepared for commitment. /// </summary> /// <param name="preparingEnlistment">A <see cref="T:System.Transactions.PreparingEnlistment"/> object used to send a response to the transaction manager.</param> public void Prepare(PreparingEnlistment preparingEnlistment) { onTxComplete(); try { using (var machineStoreForApplication = IsolatedStorageFile.GetMachineStoreForDomain()) { var name = TransactionRecoveryInformationFileName; using (var file = machineStoreForApplication.CreateFile(name + ".temp")) using (var writer = new BinaryWriter(file)) { writer.Write(session.ResourceManagerId.ToString()); writer.Write(PromotableRavenClientEnlistment.GetLocalOrDistributedTransactionId(transaction).ToString()); writer.Write(session.DatabaseName ?? ""); writer.Write(preparingEnlistment.RecoveryInformation()); file.Flush(true); } machineStoreForApplication.MoveFile(name + ".temp", name); } } catch (Exception e) { logger.ErrorException("Could not prepare distributed transaction", e); preparingEnlistment.ForceRollback(e); return; } preparingEnlistment.Prepared(); }
public void Prepare(PreparingEnlistment preparingEnlistment) { CheckDisposed(); Log.Debug($"Two-phase transaction prepare (localid={_txId})", _connector.Id); // The PostgreSQL prepared transaction name is the distributed GUID + our connection's process ID, for uniqueness _preparedTxName = $"{_transaction.TransactionInformation.DistributedIdentifier}/{_connector.BackendProcessId}"; try { using (_connector.StartUserAction()) _connector.ExecuteInternalCommand($"PREPARE TRANSACTION '{_preparedTxName}'"); // The MSDTC, which manages escalated distributed transactions, performs the 2nd phase // asynchronously - this means that TransactionScope.Dispose() will return before all // resource managers have actually commit. // If the same connection tries to enlist to a new TransactionScope immediately after // disposing an old TransactionScope, its EnlistedTransaction must have been cleared // (or we'll throw a double enlistment exception). This must be done here at the 1st phase // (which is sync). if (_connector.Connection != null) { _connector.Connection.EnlistedTransaction = null; } preparingEnlistment.Prepared(); } catch (Exception e) { Dispose(); preparingEnlistment.ForceRollback(e); } }
void IEnlistmentNotification.Prepare(PreparingEnlistment preparingEnlistment) { bool flag = false; try { IAsyncResult result = new PrepareAsyncResult(this, handleEndPrepare, preparingEnlistment); if (result.CompletedSynchronously) { PrepareAsyncResult.End(result); preparingEnlistment.Prepared(); } flag = true; } catch (TransactionException) { } finally { if (!flag) { preparingEnlistment.ForceRollback(); } } }
public virtual void Prepare(PreparingEnlistment preparingEnlistment) { try { this.dataAccessObjectDataContext?.Commit(this, false); preparingEnlistment.Prepared(); } catch (TransactionAbortedException) { throw; } catch (Exception e) { foreach (var persistenceTransactionContext in this.persistenceTransactionContextsBySqlDatabaseContexts.Values) { persistenceTransactionContext.sqlDatabaseCommandsContext.Rollback(); } preparingEnlistment.ForceRollback(e); this.Dispose(); } finally { this.Dispose(); } }
public void Prepare(PreparingEnlistment preparingEnlistment) { if (_transaction != null && !_transaction.HasMutations) { // In the case where our resource manager doesn't have any mutations, it was a read, // which we will no-op and allow through even if it was a two phase commit. // This allows cases such as nested transactions where the inner transaction is a readonly // timestamp bound read and doesn't have anything to commit. Logger.Debug(() => "Received a PREPARE for a two phase commit but without changes. This is allowed."); preparingEnlistment.Prepared(); return; } Logger.Warn(() => "Received a call to Prepare, which indicates two phase commit inside a transaction scope. This is currently not supported in Spanner."); try { preparingEnlistment.ForceRollback(new NotSupportedException( "Spanner only supports single phase commit (Prepare not supported)." + " This error can happen when attempting to use multiple transaction resources but may also happen for" + " other reasons that cause a Transaction to use two-phase commit.")); } finally { // We've forced a rollback, but the expectation is that *this* resource // manager won't have done anything yet, given that we've "failed" to prepare. // Therefore we need to clean ourselves up. The other resource managers that have already // been prepared will be cleaned up by the transaction manager. Dispose(); } }
void IEnlistmentNotification.Prepare(PreparingEnlistment preparingEnlistment) { using (new SessionIdLoggingContext(sessionImplementor.SessionId)) { try { using (var tx = new TransactionScope(AmbientTransation)) { if (sessionImplementor.ConnectionManager.IsConnected) { using (sessionImplementor.ConnectionManager.FlushingFromDtcTransaction) { sessionImplementor.BeforeTransactionCompletion(null); foreach (var dependentSession in sessionImplementor.ConnectionManager.DependentSessions) { dependentSession.BeforeTransactionCompletion(null); } logger.Debug("prepared for DTC transaction"); tx.Complete(); } } } preparingEnlistment.Prepared(); } catch (Exception exception) { logger.Error("DTC transaction prepare phase failed", exception); preparingEnlistment.ForceRollback(exception); } } }
/// <summary> /// Notifies an enlisted object that a transaction is being prepared for commitment. /// </summary> /// <param name="preparingEnlistment">A <see cref="T:System.Transactions.PreparingEnlistment"/> object used to send a response to the transaction manager.</param> public void Prepare(PreparingEnlistment preparingEnlistment) { try { onTxComplete(); ctx.CreateFile(TransactionRecoveryInformationFileName, stream => { var writer = new BinaryWriter(stream); writer.Write(session.ResourceManagerId.ToString()); writer.Write(transaction.LocalIdentifier); writer.Write(session.DatabaseName ?? ""); writer.Write(preparingEnlistment.RecoveryInformation()); }); session.PrepareTransaction(transaction.LocalIdentifier); } catch (Exception e) { logger.ErrorException("Could not prepare distributed transaction", e); try { session.Rollback(transaction.LocalIdentifier); DeleteFile(); } catch (Exception e2) { logger.ErrorException("Could not roll back transaction after prepare failed", e2); } preparingEnlistment.ForceRollback(e); return; } preparingEnlistment.Prepared(); }
/// <summary> /// Notifies an enlisted object that a transaction is being prepared for commitment. /// </summary> /// <param name="preparingEnlistment">A <see cref="T:System.Transactions.PreparingEnlistment"/> object used to send a response to the transaction manager.</param> public void Prepare(PreparingEnlistment preparingEnlistment) { onTxComplete(); session.StoreRecoveryInformation(session.ResourceManagerId, PromotableRavenClientEnlistment.GetLocalOrDistributedTransactionId(transaction), preparingEnlistment.RecoveryInformation()); preparingEnlistment.Prepared(); }
void IEnlistmentNotification.Prepare(PreparingEnlistment preparingEnlistment) { using (new SessionIdLoggingContext(sessionImplementor.SessionId)) { try { using (var tx = new TransactionScope(AmbientTransation)) { sessionImplementor.BeforeTransactionCompletion(null); //if (sessionImplementor.FlushMode != FlushMode.Never && sessionImplementor.ConnectionManager.IsConnected) //{ // using (sessionImplementor.ConnectionManager.FlushingFromDtcTransaction) // { // logger.Debug(string.Format("[session-id={0}] Flushing from Dtc Transaction", sessionImplementor.SessionId)); // sessionImplementor.Flush(); // } //} logger.Debug("prepared for DTC transaction"); tx.Complete(); } preparingEnlistment.Prepared(); } catch (Exception exception) { logger.Error("DTC transaction prepre phase failed", exception); preparingEnlistment.ForceRollback(exception); } } }
/// <summary> /// Notifies an enlisted object that a transaction is being prepared /// for commitment. /// </summary> /// <param name="preparingEnlistment"> /// A <see cref="T:System.Transactions.PreparingEnlistment" /> object /// used to send a response to the transaction manager. /// </param> public void Prepare(PreparingEnlistment preparingEnlistment) { try { #if DEBUG Console.WriteLine( "{0}.Prepare(...) (try) - {1}", this.GetType(), this.managedPath); #endif this.ManagedFileStream = this.OnPrepareFileStream(this.managedPath); preparingEnlistment.Prepared(); } catch (Exception e) { #if DEBUG Console.WriteLine( "{0}.Prepare(...) (catch) - {1}", this.GetType(), this.managedPath); #endif // Rollback() is not called on a resource manager // if its Prepare() method votes for rollback. if (!this.disposed) { this.OnRollback(); } preparingEnlistment.ForceRollback(e); } }
void IEnlistmentNotification.Prepare(PreparingEnlistment preparingEnlistment) { bool success = false; try { IAsyncResult result = new PrepareAsyncResult(this, TransactionContext.handleEndPrepare, preparingEnlistment); if (result.CompletedSynchronously) { PrepareAsyncResult.End(result); preparingEnlistment.Prepared(); } success = true; } //we need to swollow the TransactionException as it could because another party aborting it catch (TransactionException) { } finally { if (!success) { preparingEnlistment.ForceRollback(); } } }
static void HandleEndPrepare(IAsyncResult result) { PreparingEnlistment preparingEnlistment = (PreparingEnlistment)result.AsyncState; bool success = false; try { if (!result.CompletedSynchronously) { PrepareAsyncResult.End(result); preparingEnlistment.Prepared(); } success = true; } //we need to swollow the TransactionException as it could because another party aborting it catch (TransactionException) { } finally { if (!success) { preparingEnlistment.ForceRollback(); } } }
public void Prepare(PreparingEnlistment preparingEnlistment) { uint method = 0x4fe; this.TrEntry(method, new object[] { preparingEnlistment }); Exception e = null; bool flag = false; try { if (base.asyncFailureNotify != null) { base.TrText(method, "Rollback the tx as we have an async failure"); preparingEnlistment.ForceRollback(base.asyncFailureNotify); flag = true; } else { base.TrText(method, "Hconn =" + base.hconn.Value + " has been asked to Prepare by the Transaction Co-ordinator"); base.MQRMIXAEnd(); if (base.MQRMIXAPrepare(preparingEnlistment.RecoveryInformation()) == 3) { flag = true; preparingEnlistment.Done(); } else { base.TrText(method, "WMQ .NET is now prepared.."); preparingEnlistment.Prepared(); } } } catch (MQException exception2) { base.TrException(method, exception2, 1); e = exception2; preparingEnlistment.ForceRollback(e); flag = true; } catch (Exception exception3) { base.TrException(method, exception3, 2); e = exception3; preparingEnlistment.ForceRollback(e); flag = true; } finally { if (flag) { this.rmiTxComplete = true; if (base.hconn != null) { base.hconn.PulseCommitWait(); } } base.TrExit(method); } }
public void Prepare(PreparingEnlistment preparingEnlistment) { logger.Info("ue p"); Undertaker(); preparingEnlistment.Prepared(); }
void IEnlistmentNotification.Prepare(PreparingEnlistment preparingEnlistment) { if (preparingEnlistment == null) { throw new ArgumentNullException(); } preparingEnlistment.Prepared(); }
/// <summary> /// Prepares a transaction for commitment. /// </summary> /// <param name="prepareEnlistment">Facilitates communication bewtween an enlisted transaction participant and the /// transaction manager during the final phase of the transaction.</param> public virtual void Prepare(PreparingEnlistment preparingEnlistment) { // This will signal the base transaction object that no special preparation required. A class can override this // behavior if required, but since the preparation, commit and reject logic are done on different threads than the // thread where all the work to access the data occurs, any thread based locking is prohibited in the preparation phase // of the commit. preparingEnlistment.Prepared(); }
/// <summary> /// Prepare the session for the transaction commit. Run /// <see cref="ISessionImplementor.BeforeTransactionCompletion(ITransaction)"/> for the session and for /// <see cref="ConnectionManager.DependentSessions"/> if any. <see cref="Lock"/> the context /// before signaling it is done, or before rollback in case of failure. /// </summary> /// <param name="preparingEnlistment">The object for notifying the prepare phase outcome.</param> public virtual void Prepare(PreparingEnlistment preparingEnlistment) { _preparing = true; using (_session.BeginContext()) { try { using (_session.ConnectionManager.BeginProcessingFromSystemTransaction(_useConnectionOnSystemTransactionPrepare)) { if (_useConnectionOnSystemTransactionPrepare) { // Ensure any newly acquired connection gets enlisted in the transaction. When distributed, // this code runs from another thread and we cannot rely on Transaction.Current. using (var tx = new TransactionScope(EnlistedTransaction)) { // Required when both connection auto-enlistment and session auto-enlistment are disabled. _session.JoinTransaction(); _session.BeforeTransactionCompletion(null); foreach (var dependentSession in _session.ConnectionManager.DependentSessions) { dependentSession.BeforeTransactionCompletion(null); } tx.Complete(); } } else { _session.BeforeTransactionCompletion(null); foreach (var dependentSession in _session.ConnectionManager.DependentSessions) { dependentSession.BeforeTransactionCompletion(null); } } } // Lock the session to ensure second phase gets done before the session is used by code following // the transaction scope disposal. Lock(); _logger.Debug("Prepared for system transaction"); _preparing = false; preparingEnlistment.Prepared(); } catch (Exception exception) { _preparing = false; _logger.Error(exception, "System transaction prepare phase failed"); try { CompleteTransaction(false); } finally { preparingEnlistment.ForceRollback(exception); } } } }
public virtual void Prepare(PreparingEnlistment preparingEnlistment) { if (_Prepared) { throw new ApplicationException("prepare called before"); } _Prepared = true; preparingEnlistment.Prepared(); }
/// <summary> /// Notifies an enlisted object that a transaction is being prepared for commitment. /// </summary> /// <param name="preparingEnlistment"> /// A <see cref="T:System.Transactions.PreparingEnlistment"/> object used to send a response to the transaction manager. /// </param> public void Prepare(PreparingEnlistment preparingEnlistment) { if (preparingEnlistment == null) { throw new ArgumentNullException("preparingEnlistment"); } preparingEnlistment.Prepared(); }
public void Prepare(PreparingEnlistment preparingEnlistment) { this.CheckDisposed(); if (!this._transaction.IsValid(false)) { preparingEnlistment.ForceRollback(); return; } preparingEnlistment.Prepared(); }
public void Prepare(PreparingEnlistment preparingEnlistment) { Console.WriteLine("preparing..."); if (prepare) { throw new OmfgExceptionThisIsBad("prepareHook"); } preparingEnlistment.Prepared(); Console.WriteLine("done preparing!"); }
public void Prepare(PreparingEnlistment preparingEnlistment) { if (_ThrowIt) { preparingEnlistment.ForceRollback(new ApplicationException("this one went astray")); } else { preparingEnlistment.Prepared(); } }
public void Prepare(PreparingEnlistment preparingEnlistment) { if (_transaction.IsValid(false) == false) { preparingEnlistment.ForceRollback(); } else { preparingEnlistment.Prepared(); } }
public void Prepare(PreparingEnlistment preparingEnlistment) { switch (_phase1Vote) { case Phase1Vote.Prepared: { preparingEnlistment.Prepared(); break; } case Phase1Vote.ForceRollback: { preparingEnlistment.ForceRollback(); break; } case Phase1Vote.Done: { preparingEnlistment.Done(); break; } } }
public void Prepare(PreparingEnlistment preparingEnlistment) { switch (_phase1Vote) { case Phase1Vote.Prepared: { if (_volatileEnlistDuringPrepare) { TestEnlistment newVol = new TestEnlistment(_phase1Vote, _expectedOutcome); try { _txToEnlist.EnlistVolatile(newVol, EnlistmentOptions.None); Assert.Equal(_expectEnlistToSucceed, true); } catch (Exception) { Assert.Equal(_expectEnlistToSucceed, false); } } preparingEnlistment.Prepared(); break; } case Phase1Vote.ForceRollback: { if (_outcomeReceived != null) { _outcomeReceived.Set(); } preparingEnlistment.ForceRollback(); break; } case Phase1Vote.Done: { if (_outcomeReceived != null) { _outcomeReceived.Set(); } preparingEnlistment.Done(); break; } } }
public void Prepare(PreparingEnlistment preparingEnlistment) { if (_enlistDuringPrepare) { Trace(string.Format("MyEnlistment.Prepare - attempting another enlistment with options {0}", _enlistOptions.ToString())); try { MyEnlistment enlist2 = new MyEnlistment( _secondEnlistmentCompleted, /*votePrepared=*/ true, /*enlistDuringPrepare=*/ false, _enlistOptions); this.TransactionToEnlist.EnlistVolatile(enlist2, _enlistOptions); if (!_expectSuccessfulEnlist) { // Force rollback of the transaction because the second enlistment was unsuccessful. Trace("MyEnlistment.Prepare - Force Rollback because second enlistment succeeded unexpectedly"); _aborted = true; _outcomeReceived.Set(); preparingEnlistment.ForceRollback(new Exception("MyEnlistment voted ForceRollback")); return; } } catch (Exception ex) { if (_expectSuccessfulEnlist) { Trace(string.Format("MyEnlistment.Prepare - Force Rollback because second enlistment failed unexpectedly - {0}; {1}", ex.GetType().ToString(), ex.ToString())); // Force rollback of the transaction because the second enlistment was unsuccessful. _aborted = true; _outcomeReceived.Set(); preparingEnlistment.ForceRollback(new Exception("MyEnlistment voted ForceRollback")); return; } } } if (_votePrepared) { Trace("MyEnlistment.Prepare voting Prepared"); preparingEnlistment.Prepared(); } else { Trace("MyEnlistment.Prepare - Force Rollback"); _aborted = true; _outcomeReceived.Set(); preparingEnlistment.ForceRollback(new Exception("MyEnlistment voted ForceRollback")); } }
public void Prepare(PreparingEnlistment preparingEnlistment) { resource.NumPrepare++; if (resource.IgnorePrepare) return; if (resource.FailPrepare) { if (resource.FailWithException) preparingEnlistment.ForceRollback(resource.ThrowThisException ?? new NotSupportedException()); else preparingEnlistment.ForceRollback(); } else { preparingEnlistment.Prepared(); } }
public void Prepare(PreparingEnlistment preparingEnlistment) { try { dtcControlEvent.Reset(); Tracer.Debug("Prepare notification received for TX id: " + this.transactionId); BeforeEnd(); // Before sending the request to the broker, log the recovery bits, if // this fails we can't prepare and the TX should be rolled back. RecoveryLogger.LogRecoveryInfo(this.transactionId as XATransactionId, preparingEnlistment.RecoveryInformation()); // Inform the broker that work on the XA'sh TX Branch is complete. TransactionInfo info = new TransactionInfo(); info.ConnectionId = this.connection.ConnectionId; info.TransactionId = this.transactionId; info.Type = (int) TransactionType.End; this.connection.CheckConnected(); this.connection.SyncRequest(info); // Prepare the Transaction for commit. info.Type = (int) TransactionType.Prepare; IntegerResponse response = (IntegerResponse) this.connection.SyncRequest(info); if(response.Result == XA_READONLY) { Tracer.Debug("Transaction Prepare done and doesn't need a commit, TX id: " + this.transactionId); this.transactionId = null; this.currentEnlistment = null; // Read Only means there's nothing to recover because there was no // change on the broker. RecoveryLogger.LogRecovered(this.transactionId as XATransactionId); // if server responds that nothing needs to be done, then reply prepared // but clear the current state data so we appear done to the commit method. preparingEnlistment.Prepared(); // Done so commit won't be called. AfterCommit(); } else { Tracer.Debug("Transaction Prepare succeeded TX id: " + this.transactionId); // If work finished correctly, reply prepared preparingEnlistment.Prepared(); } } catch(Exception ex) { Tracer.DebugFormat("Transaction[{0}] Prepare failed with error: {1}", this.transactionId, ex.Message); AfterRollback(); preparingEnlistment.ForceRollback(); try { this.connection.OnException(ex); } catch (Exception error) { Tracer.Error(error.ToString()); } this.currentEnlistment = null; this.transactionId = null; } finally { this.dtcControlEvent.Set(); } }