//------------------------------------------------------------------------------
//
// 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);
}
}
}