//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ using Experimental.System.Messaging.Interop; using System; using System.Threading; namespace Experimental.System.Messaging { /// /// /// [To be supplied.] /// public class MessageQueueTransaction : IDisposable { private ITransaction internalTransaction; private MessageQueueTransactionStatus transactionStatus; private bool disposed; /// /// /// /// Creates a new Message Queuing internal transaction context. /// /// public MessageQueueTransaction() { this.transactionStatus = MessageQueueTransactionStatus.Initialized; } internal ITransaction InnerTransaction { get { return this.internalTransaction; } } /// /// /// /// The status of the transaction that this object represents. /// /// public MessageQueueTransactionStatus Status { get { return this.transactionStatus; } } /// /// /// /// Rolls back the pending internal transaction. /// /// public void Abort() { lock (this) { if (this.internalTransaction == null) throw new InvalidOperationException(Res.GetString(Res.TransactionNotStarted)); else { this.AbortInternalTransaction(); } } } /// /// private void AbortInternalTransaction() { int status = this.internalTransaction.Abort(0, 0, 0); if (MessageQueue.IsFatalError(status)) throw new MessageQueueException(status); this.internalTransaction = null; this.transactionStatus = MessageQueueTransactionStatus.Aborted; } /// /// /// /// Begins a new Message Queuing internal transaction context. /// /// public void Begin() { //Won't allow begining a new transaction after the object has been disposed. if (this.disposed) throw new ObjectDisposedException(GetType().Name); lock (this) { if (internalTransaction != null) throw new InvalidOperationException(Res.GetString(Res.TransactionStarted)); else { int status = SafeNativeMethods.MQBeginTransaction(out this.internalTransaction); if (MessageQueue.IsFatalError(status)) { this.internalTransaction = null; throw new MessageQueueException(status); } this.transactionStatus = MessageQueueTransactionStatus.Pending; } } } /// /// internal ITransaction BeginQueueOperation() { #pragma warning disable 0618 //@ Monitor.Enter(this); #pragma warning restore 0618 return this.internalTransaction; } /// /// /// /// Commits a pending internal transaction. /// /// public void Commit() { lock (this) { if (this.internalTransaction == null) throw new InvalidOperationException(Res.GetString(Res.TransactionNotStarted)); else { int status = this.internalTransaction.Commit(0, 0, 0); if (MessageQueue.IsFatalError(status)) throw new MessageQueueException(status); this.internalTransaction = null; this.transactionStatus = MessageQueueTransactionStatus.Committed; } } } /// /// /// /// Disposes this transaction instance, if it is in a /// pending status, the transaction will be aborted. /// /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// /// /// /// protected virtual void Dispose(bool disposing) { if (disposing) { lock (this) { if (internalTransaction != null) this.AbortInternalTransaction(); } } this.disposed = true; } /// /// ~MessageQueueTransaction() { Dispose(false); } /// /// internal void EndQueueOperation() { Monitor.Exit(this); } } }