MessageQueueTransaction.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. //------------------------------------------------------------------------------
  2. // <copyright file="MessageQueueTransaction.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. //------------------------------------------------------------------------------
  6. using Experimental.System.Messaging.Interop;
  7. using System;
  8. using System.Threading;
  9. namespace Experimental.System.Messaging
  10. {
  11. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction"]/*' />
  12. /// <devdoc>
  13. /// <para>[To be supplied.]</para>
  14. /// </devdoc>
  15. public class MessageQueueTransaction : IDisposable
  16. {
  17. private ITransaction internalTransaction;
  18. private MessageQueueTransactionStatus transactionStatus;
  19. private bool disposed;
  20. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction.MessageQueueTransaction"]/*' />
  21. /// <devdoc>
  22. /// <para>
  23. /// Creates a new Message Queuing internal transaction context.
  24. /// </para>
  25. /// </devdoc>
  26. public MessageQueueTransaction()
  27. {
  28. this.transactionStatus = MessageQueueTransactionStatus.Initialized;
  29. }
  30. internal ITransaction InnerTransaction
  31. {
  32. get
  33. {
  34. return this.internalTransaction;
  35. }
  36. }
  37. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction.Status"]/*' />
  38. /// <devdoc>
  39. /// <para>
  40. /// The status of the transaction that this object represents.
  41. /// </para>
  42. /// </devdoc>
  43. public MessageQueueTransactionStatus Status
  44. {
  45. get
  46. {
  47. return this.transactionStatus;
  48. }
  49. }
  50. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction.Abort"]/*' />
  51. /// <devdoc>
  52. /// <para>
  53. /// Rolls back the pending internal transaction.
  54. /// </para>
  55. /// </devdoc>
  56. public void Abort()
  57. {
  58. lock (this)
  59. {
  60. if (this.internalTransaction == null)
  61. throw new InvalidOperationException(Res.GetString(Res.TransactionNotStarted));
  62. else
  63. {
  64. this.AbortInternalTransaction();
  65. }
  66. }
  67. }
  68. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction.AbortInternalTransaction"]/*' />
  69. /// <internalonly/>
  70. private void AbortInternalTransaction()
  71. {
  72. int status = this.internalTransaction.Abort(0, 0, 0);
  73. if (MessageQueue.IsFatalError(status))
  74. throw new MessageQueueException(status);
  75. this.internalTransaction = null;
  76. this.transactionStatus = MessageQueueTransactionStatus.Aborted;
  77. }
  78. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction.Begin"]/*' />
  79. /// <devdoc>
  80. /// <para>
  81. /// Begins a new Message Queuing internal transaction context.
  82. /// </para>
  83. /// </devdoc>
  84. public void Begin()
  85. {
  86. //Won't allow begining a new transaction after the object has been disposed.
  87. if (this.disposed)
  88. throw new ObjectDisposedException(GetType().Name);
  89. lock (this)
  90. {
  91. if (internalTransaction != null)
  92. throw new InvalidOperationException(Res.GetString(Res.TransactionStarted));
  93. else
  94. {
  95. int status = SafeNativeMethods.MQBeginTransaction(out this.internalTransaction);
  96. if (MessageQueue.IsFatalError(status))
  97. {
  98. this.internalTransaction = null;
  99. throw new MessageQueueException(status);
  100. }
  101. this.transactionStatus = MessageQueueTransactionStatus.Pending;
  102. }
  103. }
  104. }
  105. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction.BeginQueueOperation"]/*' />
  106. /// <internalonly/>
  107. internal ITransaction BeginQueueOperation()
  108. {
  109. #pragma warning disable 0618
  110. //@
  111. Monitor.Enter(this);
  112. #pragma warning restore 0618
  113. return this.internalTransaction;
  114. }
  115. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction.Commit"]/*' />
  116. /// <devdoc>
  117. /// <para>
  118. /// Commits a pending internal transaction.
  119. /// </para>
  120. /// </devdoc>
  121. public void Commit()
  122. {
  123. lock (this)
  124. {
  125. if (this.internalTransaction == null)
  126. throw new InvalidOperationException(Res.GetString(Res.TransactionNotStarted));
  127. else
  128. {
  129. int status = this.internalTransaction.Commit(0, 0, 0);
  130. if (MessageQueue.IsFatalError(status))
  131. throw new MessageQueueException(status);
  132. this.internalTransaction = null;
  133. this.transactionStatus = MessageQueueTransactionStatus.Committed;
  134. }
  135. }
  136. }
  137. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction.Dispose"]/*' />
  138. /// <devdoc>
  139. /// <para>
  140. /// Disposes this transaction instance, if it is in a
  141. /// pending status, the transaction will be aborted.
  142. /// </para>
  143. /// </devdoc>
  144. public void Dispose()
  145. {
  146. Dispose(true);
  147. GC.SuppressFinalize(this);
  148. }
  149. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction.Dispose1"]/*' />
  150. /// <devdoc>
  151. /// <para>
  152. /// </para>
  153. /// </devdoc>
  154. protected virtual void Dispose(bool disposing)
  155. {
  156. if (disposing)
  157. {
  158. lock (this)
  159. {
  160. if (internalTransaction != null)
  161. this.AbortInternalTransaction();
  162. }
  163. }
  164. this.disposed = true;
  165. }
  166. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction.Finalize"]/*' />
  167. /// <internalonly/>
  168. ~MessageQueueTransaction()
  169. {
  170. Dispose(false);
  171. }
  172. /// <include file='doc\MessageQueueTransaction.uex' path='docs/doc[@for="MessageQueueTransaction.EndQueueOperation"]/*' />
  173. /// <internalonly/>
  174. internal void EndQueueOperation()
  175. {
  176. Monitor.Exit(this);
  177. }
  178. }
  179. }