PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/core/src/main/java/org/infinispan/transaction/impl/TotalOrderRemoteTransactionState.java

http://github.com/infinispan/infinispan
Java | 237 lines | 148 code | 31 blank | 58 comment | 32 complexity | 3f588481f8f36fff243db00e498419e0 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1
  1. package org.infinispan.transaction.impl;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.Collections;
  5. import java.util.EnumSet;
  6. import java.util.List;
  7. import org.infinispan.transaction.totalorder.TotalOrderLatch;
  8. import org.infinispan.transaction.xa.GlobalTransaction;
  9. import org.infinispan.util.logging.Log;
  10. import org.infinispan.util.logging.LogFactory;
  11. /**
  12. * Represents a state for a Remote Transaction when the Total Order based protocol is used.
  13. *
  14. * @author Pedro Ruivo
  15. * @since 5.3
  16. */
  17. public class TotalOrderRemoteTransactionState {
  18. private static final Log log = LogFactory.getLog(TotalOrderRemoteTransactionState.class);
  19. private static final boolean trace = log.isTraceEnabled();
  20. private final EnumSet<State> transactionState;
  21. private final GlobalTransaction globalTransaction;
  22. private List<Object> lockedKeys;
  23. private TotalOrderLatch block;
  24. private List<TotalOrderLatch> dependencies;
  25. public TotalOrderRemoteTransactionState(GlobalTransaction globalTransaction) {
  26. this.transactionState = EnumSet.noneOf(State.class);
  27. this.globalTransaction = globalTransaction;
  28. }
  29. /**
  30. * check if the transaction is marked for rollback (by the Rollback Command)
  31. *
  32. * @return true if it is marked for rollback, false otherwise
  33. */
  34. public synchronized boolean isRollbackReceived() {
  35. return transactionState.contains(State.ROLLBACK_ONLY);
  36. }
  37. /**
  38. * check if the transaction is marked for commit (by the Commit Command)
  39. *
  40. * @return true if it is marked for commit, false otherwise
  41. */
  42. public synchronized boolean isCommitReceived() {
  43. return transactionState.contains(State.COMMIT_ONLY);
  44. }
  45. /**
  46. * mark the transaction as prepared (the validation was finished) and notify a possible pending commit or rollback
  47. * command
  48. */
  49. public synchronized void prepared() {
  50. if (trace) {
  51. log.tracef("[%s] Current status is %s, setting status to: PREPARED", globalTransaction.globalId(),
  52. transactionState);
  53. }
  54. transactionState.add(State.PREPARED);
  55. notifyAll();
  56. }
  57. /**
  58. * mark the transaction as preparing, blocking the commit and rollback commands until the {@link #prepared()} is
  59. * invoked
  60. */
  61. public synchronized void preparing() {
  62. if (trace) {
  63. log.tracef("[%s] Current status is %s, setting status to: PREPARING", globalTransaction.globalId(),
  64. transactionState);
  65. }
  66. transactionState.add(State.PREPARING);
  67. }
  68. /**
  69. * Commit and rollback commands invokes this method and they are blocked here if the state is PREPARING
  70. *
  71. * @param commit true if it is a commit command, false otherwise
  72. * @return true if the command needs to be processed, false otherwise
  73. * @throws InterruptedException when it is interrupted while waiting
  74. */
  75. public final synchronized boolean waitUntilPrepared(boolean commit)
  76. throws InterruptedException {
  77. boolean result;
  78. State state = commit ? State.COMMIT_ONLY : State.ROLLBACK_ONLY;
  79. if (trace) {
  80. log.tracef("[%s] Current status is %s, setting status to: %s", globalTransaction.globalId(),
  81. transactionState, state);
  82. }
  83. transactionState.add(state);
  84. if (transactionState.contains(State.PREPARED)) {
  85. result = true;
  86. if (trace) {
  87. log.tracef("[%s] Transaction is PREPARED", globalTransaction.globalId());
  88. }
  89. } else if (transactionState.contains(State.PREPARING)) {
  90. wait();
  91. result = true;
  92. if (trace) {
  93. log.tracef("[%s] Transaction was in PREPARING state but now it is prepared", globalTransaction.globalId());
  94. }
  95. } else {
  96. if (trace) {
  97. log.tracef("[%s] Transaction is not delivered yet", globalTransaction.globalId());
  98. }
  99. result = false;
  100. }
  101. return result;
  102. }
  103. /**
  104. * @return true if the transaction has received the prepare and the commit or rollback
  105. */
  106. public final synchronized boolean isFinished() {
  107. return transactionState.contains(State.PREPARED) &&
  108. (transactionState.contains(State.COMMIT_ONLY) || transactionState.contains(State.ROLLBACK_ONLY));
  109. }
  110. /**
  111. * @return the keys locked in {@code org.infinispan.transaction.totalorder.TotalOrderManager}
  112. */
  113. public final synchronized Collection<Object> getLockedKeys() {
  114. return lockedKeys;
  115. }
  116. /**
  117. * @return the {@code TotalOrderLatch} associated to this transaction
  118. */
  119. public final synchronized TotalOrderLatch getTransactionSynchronizedBlock() {
  120. return block;
  121. }
  122. /**
  123. * Sets the {@code TotalOrderLatch} to be associated to this transaction
  124. */
  125. public final synchronized void setTransactionSynchronizedBlock(TotalOrderLatch block) {
  126. this.block = block;
  127. }
  128. /**
  129. * @return the global transaction
  130. */
  131. public final synchronized GlobalTransaction getGlobalTransaction() {
  132. return globalTransaction;
  133. }
  134. public final synchronized void awaitUntilReset() throws InterruptedException {
  135. while (block != null && lockedKeys != null) {
  136. wait();
  137. }
  138. }
  139. public final synchronized void reset() {
  140. this.block = null;
  141. this.lockedKeys = null;
  142. notifyAll();
  143. }
  144. @Override
  145. public String toString() {
  146. return "TotalOrderRemoteTransactionState{" +
  147. "transactionState=" + transactionState +
  148. ", globalTransaction='" + globalTransaction.globalId() + '\'' +
  149. '}';
  150. }
  151. @Override
  152. public boolean equals(Object o) {
  153. if (this == o) return true;
  154. if (o == null || getClass() != o.getClass()) return false;
  155. TotalOrderRemoteTransactionState state = (TotalOrderRemoteTransactionState) o;
  156. return !(globalTransaction != null ? !globalTransaction.equals(state.globalTransaction) :
  157. state.globalTransaction != null);
  158. }
  159. @Override
  160. public int hashCode() {
  161. return globalTransaction != null ? globalTransaction.hashCode() : 0;
  162. }
  163. public final synchronized void addSynchronizedBlock(TotalOrderLatch block) {
  164. if (dependencies == null) {
  165. dependencies = new ArrayList<TotalOrderLatch>(8);
  166. }
  167. dependencies.add(block);
  168. }
  169. public final synchronized void addAllSynchronizedBlocks(Collection<TotalOrderLatch> blocks) {
  170. if (dependencies == null) {
  171. dependencies = new ArrayList<TotalOrderLatch>(blocks);
  172. } else {
  173. dependencies.addAll(blocks);
  174. }
  175. }
  176. public final synchronized void addKeysLockedForClear() {
  177. lockedKeys = null;
  178. }
  179. public final synchronized void addLockedKey(Object key) {
  180. if (lockedKeys == null) {
  181. lockedKeys = new ArrayList<Object>(8);
  182. }
  183. lockedKeys.add(key);
  184. }
  185. public synchronized Collection<TotalOrderLatch> getConflictingTransactionBlocks() {
  186. return dependencies == null ? Collections.<TotalOrderLatch>emptyList() : dependencies;
  187. }
  188. private static enum State {
  189. /**
  190. * the prepare command was received and started the validation
  191. */
  192. PREPARING,
  193. /**
  194. * the prepare command was received and finished the validation
  195. */
  196. PREPARED,
  197. /**
  198. * the rollback command was received before the prepare command and the transaction must be aborted
  199. */
  200. ROLLBACK_ONLY,
  201. /**
  202. * the commit command was received before the prepare command and the transaction must be committed
  203. */
  204. COMMIT_ONLY
  205. }
  206. }