private async Task <TransactionalStatus> CommitReadWriteTransaction(TransactionInfo transactionInfo, List <ParticipantId> writeResources) { ParticipantId manager = SelectManager(transactionInfo, writeResources); Dictionary <ParticipantId, AccessCounter> participants = transactionInfo.Participants; foreach (var p in participants .SelectResources() .Where(kvp => !kvp.Key.Equals(manager))) { // one-way prepare message p.Key.Reference.AsReference <ITransactionalResourceExtension>() .Prepare(p.Key.Name, transactionInfo.TransactionId, p.Value, transactionInfo.TimeStamp, manager) .Ignore(); } try { // wait for the TM to commit the transaction TransactionalStatus status = await manager.Reference.AsReference <ITransactionManagerExtension>() .PrepareAndCommit(manager.Name, transactionInfo.TransactionId, participants[manager], transactionInfo.TimeStamp, writeResources, participants.Count); if (status != TransactionalStatus.Ok) { if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug($"{stopwatch.Elapsed.TotalMilliseconds:f2} fail {transactionInfo.TransactionId} TM response status={status}"); } // notify participants if (status.DefinitelyAborted()) { await Task.WhenAll(writeResources .Where(p => !p.Equals(manager)) .Select(p => p.Reference.AsReference <ITransactionalResourceExtension>() .Cancel(p.Name, transactionInfo.TransactionId, transactionInfo.TimeStamp, status))); } return(status); } } catch (TimeoutException) { if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug($"{stopwatch.Elapsed.TotalMilliseconds:f2} timeout {transactionInfo.TransactionId} TM response"); } return(TransactionalStatus.TMResponseTimeout); } if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace($"{stopwatch.Elapsed.TotalMilliseconds:f2} finish {transactionInfo.TransactionId}"); } return(TransactionalStatus.Ok); }
private async Task <TransactionalStatus> CommitReadWriteTransaction(TransactionInfo transactionInfo, List <ParticipantId> writeResources, List <KeyValuePair <ParticipantId, AccessCounter> > resources, KeyValuePair <ParticipantId, AccessCounter> manager) { TransactionalStatus status = TransactionalStatus.Ok; try { foreach (var p in resources) { if (p.Key.Equals(manager.Key)) { continue; } // one-way prepare message p.Key.Reference.AsReference <ITransactionalResourceExtension>() .Prepare(p.Key.Name, transactionInfo.TransactionId, p.Value, transactionInfo.TimeStamp, manager.Key) .Ignore(); } // wait for the TM to commit the transaction status = await manager.Key.Reference.AsReference <ITransactionManagerExtension>() .PrepareAndCommit(manager.Key.Name, transactionInfo.TransactionId, manager.Value, transactionInfo.TimeStamp, writeResources, resources.Count); } catch (TimeoutException) { if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug($"{stopwatch.Elapsed.TotalMilliseconds:f2} timeout {transactionInfo.TransactionId} on CommitReadWriteTransaction"); } status = TransactionalStatus.TMResponseTimeout; } catch (Exception ex) { if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug($"{stopwatch.Elapsed.TotalMilliseconds:f2} failure {transactionInfo.TransactionId} CommitReadWriteTransaction"); } this.logger.LogWarning(ex, "Unknown error while commiting transaction {TransactionId}", transactionInfo.TransactionId); status = TransactionalStatus.PresumedAbort; } if (status != TransactionalStatus.Ok) { try { if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug($"{stopwatch.Elapsed.TotalMilliseconds:f2} failed {transactionInfo.TransactionId} with status={status}"); } // notify participants if (status.DefinitelyAborted()) { await Task.WhenAll(writeResources .Where(p => !p.Equals(manager.Key)) .Select(p => p.Reference.AsReference <ITransactionalResourceExtension>() .Cancel(p.Name, transactionInfo.TransactionId, transactionInfo.TimeStamp, status))); } } catch (Exception ex) { if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug($"{stopwatch.Elapsed.TotalMilliseconds:f2} failure aborting {transactionInfo.TransactionId} CommitReadWriteTransaction"); } this.logger.LogWarning(ex, "Failed to abort transaction {TransactionId}", transactionInfo.TransactionId); } } if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace($"{stopwatch.Elapsed.TotalMilliseconds:f2} finish {transactionInfo.TransactionId}"); } return(status); }
private async Task <TransactionalStatus> CommitReadWriteTransaction(TransactionInfo transactionInfo, List <ParticipantId> writeResources) { ParticipantId tm = selectTMByBatchSize ? transactionInfo.TMCandidate : writeResources[0]; Dictionary <ParticipantId, AccessCounter> participants = transactionInfo.Participants; Task <TransactionalStatus> tmPrepareAndCommitTask = null; foreach (var p in participants) { if (p.Key.Equals(tm)) { tmPrepareAndCommitTask = p.Key.Reference.AsReference <ITransactionManagerExtension>() .PrepareAndCommit(p.Key.Name, transactionInfo.TransactionId, p.Value, transactionInfo.TimeStamp, writeResources, participants.Count); } else { // one-way prepare message p.Key.Reference.AsReference <ITransactionalResourceExtension>() .Prepare(p.Key.Name, transactionInfo.TransactionId, p.Value, transactionInfo.TimeStamp, tm) .Ignore(); } } try { // wait for the TM to commit the transaction TransactionalStatus status = await tmPrepareAndCommitTask; if (status != TransactionalStatus.Ok) { if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug($"{stopwatch.Elapsed.TotalMilliseconds:f2} fail {transactionInfo.TransactionId} TM response status={status}"); } // notify participants if (status.DefinitelyAborted()) { foreach (var p in writeResources) { if (!p.Equals(tm)) { // one-way cancel message p.Reference.AsReference <ITransactionalResourceExtension>() .Cancel(p.Name, transactionInfo.TransactionId, transactionInfo.TimeStamp, status) .Ignore(); } } } return(status); } } catch (TimeoutException) { if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug($"{stopwatch.Elapsed.TotalMilliseconds:f2} timeout {transactionInfo.TransactionId} TM response"); } return(TransactionalStatus.TMResponseTimeout); } if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace($"{stopwatch.Elapsed.TotalMilliseconds:f2} finish {transactionInfo.TransactionId}"); } return(TransactionalStatus.Ok); }