public void testAbortSupplyCause() throws Exception {
   Exception abortCause = new Exception("The cause");
   txn.abort(abortCause);
   assertAborted(abortCause);
   try {
     txn.abort(new IllegalArgumentException());
     fail("Expected TransactionNotActiveException");
   } catch (TransactionNotActiveException e) {
     System.err.println(e);
     assertEquals(abortCause, e.getCause());
   }
   assertAborted(abortCause);
   try {
     txn.abort(abortXcp);
     fail("Expected TransactionNotActiveException");
   } catch (TransactionNotActiveException e) {
     System.err.println(e);
     assertEquals(abortCause, e.getCause());
   }
   assertAborted(abortCause);
   handle.getTransaction();
   try {
     handle.commit();
     fail("Expected TransactionNotActiveException");
   } catch (TransactionNotActiveException e) {
     System.err.println(e);
     assertEquals(abortCause, e.getCause());
   }
   assertAborted(abortCause);
 }
 public void testCommitCommitted() throws Exception {
   txn.join(new DummyTransactionParticipant());
   handle.commit();
   try {
     handle.commit();
     fail("Expected IllegalStateException");
   } catch (IllegalStateException e) {
     System.err.println(e);
   }
   assertCommitted();
 }
 public void testCommitFails() throws Exception {
   DummyTransactionParticipant[] participants = {
     new DummyNonDurableTransactionParticipant(),
     new DummyNonDurableTransactionParticipant() {
       protected boolean prepareResult() {
         return true;
       }
     },
     new DummyNonDurableTransactionParticipant() {
       public void commit(Transaction txn) {
         throw new RuntimeException("Commit failed");
       }
     },
     new DummyNonDurableTransactionParticipant() {
       protected boolean prepareResult() {
         return true;
       }
     },
     new DummyTransactionParticipant() {}
   };
   for (TransactionParticipant participant : participants) {
     txn.join(participant);
   }
   handle.commit();
   for (DummyTransactionParticipant participant : participants) {
     if (!participant.prepareReturnedTrue()) {
       assertEquals(
           (participant == participants[2] ? State.PREPARED : State.COMMITTED),
           participant.getState());
     }
   }
   assertCommitted();
 }
 public void testCheckTimeoutPreparingTimedOut() throws Exception {
   final Exception[] checkTimeoutException = {null};
   DummyTransactionParticipant[] participants = {
     new DummyNonDurableTransactionParticipant() {
       public boolean prepare(Transaction txn) throws Exception {
         try {
           txn.checkTimeout();
           return super.prepare(txn);
         } catch (RuntimeException e) {
           checkTimeoutException[0] = e;
           throw e;
         }
       }
     },
     new DummyTransactionParticipant()
   };
   for (DummyTransactionParticipant participant : participants) {
     txn.join(participant);
   }
   Thread.sleep(TIMED_OUT);
   try {
     handle.commit();
     fail("Expected TransactionTimeoutException");
   } catch (TransactionTimeoutException e) {
     System.err.println(e);
     assertEquals(e, checkTimeoutException[0]);
   }
 }
 public void testCommitPrepareAbortsAndFailsLast() throws Exception {
   DummyTransactionParticipant[] participants = {
     new DummyNonDurableTransactionParticipant(),
     new DummyNonDurableTransactionParticipant() {
       protected boolean prepareResult() {
         return true;
       }
     },
     new DummyTransactionParticipant() {
       public void prepareAndCommit(Transaction txn) throws Exception {
         try {
           txn.abort(abortXcp);
         } catch (RuntimeException e) {
           fail("Unexpected exception: " + e);
         }
         throw new IOException("Prepare failed");
       }
     }
   };
   for (TransactionParticipant participant : participants) {
     txn.join(participant);
   }
   try {
     handle.commit();
     fail("Expected IOException");
   } catch (IOException e) {
     System.err.println(e);
   }
   for (DummyTransactionParticipant participant : participants) {
     if (!participant.prepareReturnedTrue()) {
       assertEquals(State.ABORTED, participant.getState());
     }
   }
   assertAborted(abortXcp);
 }
 public void testCommitAbortedWithNoCause() throws Exception {
   txn.abort(abortXcp);
   try {
     handle.commit();
     fail("Expected TransactionNotActiveException");
   } catch (TransactionNotActiveException e) {
     System.err.println(e);
     assertFalse(retryable(e));
   }
 }
 public void testCheckTimeoutCommitted() throws Exception {
   handle.commit();
   try {
     txn.checkTimeout();
     fail("Expected TransactionNotActiveException");
   } catch (TransactionNotActiveException e) {
     System.err.println(e);
   }
   handle = coordinator.createTransaction(false);
   txn = handle.getTransaction();
   Thread.sleep(TIMED_OUT);
   handle.commit();
   try {
     txn.checkTimeout();
     fail("Expected TransactionNotActiveException");
   } catch (TransactionNotActiveException e) {
     System.err.println(e);
   }
 }
 public void testCommitAborted() throws Exception {
   txn.join(new DummyTransactionParticipant());
   txn.abort(abortXcp);
   try {
     handle.commit();
     fail("Expected TransactionNotActiveException");
   } catch (TransactionNotActiveException e) {
     System.err.println(e);
   }
   assertAborted(abortXcp);
 }
 void assertCommitted() {
   assertFalse(txn.isAborted());
   assertEquals(null, txn.getAbortCause());
   try {
     handle.getTransaction().join(new DummyTransactionParticipant());
     fail("Transaction was active");
   } catch (IllegalStateException e) {
   } catch (RuntimeException e) {
     fail("Unexpected exception: " + e);
   }
 }
 public void testGetTransactionCommitting() throws Exception {
   TransactionParticipant participant =
       new DummyTransactionParticipant() {
         public void commit(Transaction txn) {
           handle.getTransaction();
           super.commit(txn);
         }
       };
   txn.join(participant);
   handle.commit();
 }
 public void testCommitAbortedWithNonRetryableCause() throws Exception {
   Exception abortCause = new IllegalArgumentException();
   txn.abort(abortCause);
   try {
     handle.commit();
     fail("Expected TransactionNotActiveException");
   } catch (TransactionNotActiveException e) {
     System.err.println(e);
     assertFalse(retryable(e));
     assertEquals(abortCause, e.getCause());
   }
   assertAborted(abortCause);
 }
 public void testCheckTimeoutCommitting() throws Exception {
   final Exception[] checkTimeoutException = {null};
   DummyTransactionParticipant participant =
       new DummyTransactionParticipant() {
         public void commit(Transaction txn) {
           try {
             txn.checkTimeout();
           } catch (RuntimeException e) {
             checkTimeoutException[0] = e;
             throw e;
           }
         }
       };
   txn.join(participant);
   handle.commit();
   assertNull(checkTimeoutException[0]);
 }
 public void testJoinPreparing() throws Exception {
   final Exception[] abortCause = {null};
   DummyTransactionParticipant[] participants = {
     new DummyNonDurableTransactionParticipant(),
     new DummyNonDurableTransactionParticipant() {
       protected boolean prepareResult() {
         return true;
       }
     },
     new DummyNonDurableTransactionParticipant() {
       public boolean prepare(Transaction txn) {
         try {
           txn.join(this);
           fail("Expected IllegalStateException");
         } catch (IllegalStateException e) {
           System.err.println(e);
           abortCause[0] = e;
           throw e;
         } catch (RuntimeException e) {
           fail("Unexpected exception: " + e);
         }
         return false;
       }
     },
     new DummyNonDurableTransactionParticipant() {
       protected boolean prepareResult() {
         return true;
       }
     }
   };
   for (TransactionParticipant participant : participants) {
     txn.join(participant);
   }
   try {
     handle.commit();
     fail("Expected IllegalStateException");
   } catch (IllegalStateException e) {
     System.err.println(e);
   }
   for (DummyTransactionParticipant participant : participants) {
     if (!participant.prepareReturnedTrue()) {
       assertEquals(State.ABORTED, participant.getState());
     }
   }
   assertAborted(abortCause[0]);
 }
 public void testAbortCommitting() throws Exception {
   DummyTransactionParticipant[] participants = {
     new DummyNonDurableTransactionParticipant(),
     new DummyNonDurableTransactionParticipant() {
       protected boolean prepareResult() {
         return true;
       }
     },
     new DummyNonDurableTransactionParticipant() {
       public void commit(Transaction txn) {
         assertNotAborted();
         try {
           txn.abort(abortXcp);
           fail("Expected IllegalStateException");
         } catch (IllegalStateException e) {
           System.err.println(e);
           throw e;
         } catch (RuntimeException e) {
           fail("Unexpected exception: " + e);
         }
       }
     },
     new DummyNonDurableTransactionParticipant() {
       protected boolean prepareResult() {
         return true;
       }
     }
   };
   for (TransactionParticipant participant : participants) {
     txn.join(participant);
   }
   handle.commit();
   for (DummyTransactionParticipant participant : participants) {
     if (!participant.prepareReturnedTrue()) {
       assertEquals(
           participant == participants[2] ? State.PREPARED : State.COMMITTED,
           participant.getState());
     }
   }
   assertCommitted();
 }
 public void testCommitActive() throws Exception {
   DummyTransactionParticipant[] participants = {
     new DummyNonDurableTransactionParticipant(),
     new DummyNonDurableTransactionParticipant() {
       protected boolean prepareResult() {
         return true;
       }
     },
     new DummyTransactionParticipant()
   };
   for (TransactionParticipant participant : participants) {
     txn.join(participant);
   }
   handle.commit();
   for (DummyTransactionParticipant participant : participants) {
     if (!participant.prepareReturnedTrue()) {
       assertEquals(State.COMMITTED, participant.getState());
     }
   }
   assertCommitted();
 }
 public void testCheckTimeoutPreparing() throws Exception {
   final Exception[] checkTimeoutException = {null};
   DummyTransactionParticipant[] participants = {
     new DummyNonDurableTransactionParticipant() {
       public boolean prepare(Transaction txn) throws Exception {
         try {
           txn.checkTimeout();
           return super.prepare(txn);
         } catch (RuntimeException e) {
           checkTimeoutException[0] = e;
           throw e;
         }
       }
     },
     new DummyTransactionParticipant()
   };
   for (DummyTransactionParticipant participant : participants) {
     txn.join(participant);
   }
   handle.commit();
   assertNull(checkTimeoutException[0]);
 }
 public void testCheckTimeoutPrepareAndCommittingTimedOut() throws Exception {
   final Exception[] checkTimeoutException = {null};
   DummyTransactionParticipant participant =
       new DummyTransactionParticipant() {
         public void prepareAndCommit(Transaction txn) {
           try {
             txn.checkTimeout();
           } catch (RuntimeException e) {
             checkTimeoutException[0] = e;
             throw e;
           }
         }
       };
   txn.join(participant);
   Thread.sleep(TIMED_OUT);
   try {
     handle.commit();
     fail("Expected TransactionTimeoutException");
   } catch (TransactionTimeoutException e) {
     System.err.println(e);
     assertEquals(e, checkTimeoutException[0]);
   }
 }
 public void testCommitPrepareFailsMiddle() throws Exception {
   final Exception abortCause = new IOException("Prepare failed");
   DummyTransactionParticipant[] participants = {
     new DummyNonDurableTransactionParticipant(),
     new DummyNonDurableTransactionParticipant() {
       protected boolean prepareResult() {
         return true;
       }
     },
     new DummyNonDurableTransactionParticipant() {
       public boolean prepare(Transaction txn) throws Exception {
         throw abortCause;
       }
     },
     new DummyNonDurableTransactionParticipant() {
       protected boolean prepareResult() {
         return true;
       }
     },
     new DummyTransactionParticipant()
   };
   for (TransactionParticipant participant : participants) {
     txn.join(participant);
   }
   try {
     handle.commit();
     fail("Expected IOException");
   } catch (IOException e) {
     System.err.println(e);
   }
   for (DummyTransactionParticipant participant : participants) {
     if (!participant.prepareReturnedTrue()) {
       assertEquals(State.ABORTED, participant.getState());
     }
   }
   assertAborted(abortCause);
 }
 public void testAbortPrepareAndCommitting() throws Exception {
   final Exception abortCause = new IllegalArgumentException();
   DummyTransactionParticipant[] participants = {
     new DummyNonDurableTransactionParticipant(),
     new DummyNonDurableTransactionParticipant() {
       protected boolean prepareResult() {
         return true;
       }
     },
     new DummyTransactionParticipant() {
       public void prepareAndCommit(Transaction txn) {
         assertNotAborted();
         try {
           txn.abort(abortCause);
         } catch (RuntimeException e) {
           fail("Unexpected exception: " + e);
         }
       }
     }
   };
   for (TransactionParticipant participant : participants) {
     txn.join(participant);
   }
   try {
     handle.commit();
     fail("Expected TransactionAbortedException");
   } catch (TransactionAbortedException e) {
     System.err.println(e);
     assertEquals(abortCause, e.getCause());
   }
   for (DummyTransactionParticipant participant : participants) {
     if (!participant.prepareReturnedTrue()) {
       assertEquals(State.ABORTED, participant.getState());
     }
   }
   assertAborted(abortCause);
 }
  /**
   * Private method that executes a single task, creating the transaction state and handling re-try
   * as appropriate. If the thread calling this method is interrupted before the task can complete
   * then this method attempts to re-schedule the task to run in another thread if {@code
   * retryOnInterruption} is {@code true} and always re-throws the associated {@code
   * InterruptedException}. Providing {@code true} for the {@code unbounded} parameter results in a
   * transaction with timeout value as specified by the value of the {@code
   * TransactionCoordinator.TXN_UNBOUNDED_TIMEOUT_PROPERTY} property.
   *
   * <p>This method returns {@code true} if the task was completed or failed permanently, and {@code
   * false} otherwise. If {@code false} is returned then the task is scheduled to be re-tried at
   * some point in the future, possibly by another thread, by this method. The caller may query the
   * status of the task and wait for the task to complete or fail permanently through the {@code
   * ScheduledTaskImpl} interface.
   */
  private boolean executeTask(
      ScheduledTaskImpl task, boolean unbounded, boolean retryOnInterruption)
      throws InterruptedException {
    logger.log(Level.FINEST, "starting a new transactional task");

    // store the current owner, and then push the new thread detail
    Identity parent = ContextResolver.getCurrentOwner();
    ContextResolver.setTaskState(kernelContext, task.getOwner());

    try {
      // keep trying to run the task until we succeed, tracking how
      // many tries it actually took
      while (true) {
        if (!task.setRunning(true)) {
          // this task is already finished
          return true;
        }

        // NOTE: We could report the two queue sizes separately,
        // so we should figure out how we want to represent these
        int waitSize = backingQueue.getReadyCount() + dependencyCount.get();
        profileCollectorHandle.startTask(
            task.getTask(), task.getOwner(), task.getStartTime(), waitSize);
        task.incrementTryCount();

        Transaction transaction = null;

        try {
          // setup the transaction state
          TransactionHandle handle = transactionCoordinator.createTransaction(unbounded);
          transaction = handle.getTransaction();
          ContextResolver.setCurrentTransaction(transaction);

          try {
            // notify the profiler and access coordinator
            profileCollectorHandle.noteTransactional(transaction.getId());
            accessCoordinator.notifyNewTransaction(
                transaction, task.getStartTime(), task.getTryCount());

            // run the task in the new transactional context
            task.getTask().run();
          } finally {
            // regardless of the outcome, always clear the current
            // transaction state before proceeding...
            ContextResolver.clearCurrentTransaction(transaction);
          }

          // try to commit the transaction...note that there's the
          // chance that the application code masked the orginal
          // cause of a failure, so we'll check for that first,
          // re-throwing the root cause in that case
          if (transaction.isAborted()) {
            throw transaction.getAbortCause();
          }
          handle.commit();

          // the task completed successfully, so we're done
          profileCollectorHandle.finishTask(task.getTryCount());
          task.setDone(null);
          return true;
        } catch (InterruptedException ie) {
          // make sure the transaction was aborted
          if (!transaction.isAborted()) {
            transaction.abort(ie);
          }
          profileCollectorHandle.finishTask(task.getTryCount(), ie);
          // if the task didn't finish because of the interruption
          // then we want to note that and possibly re-queue the
          // task to run in a usable thread
          if (task.setInterrupted() && retryOnInterruption) {
            if (!handoffRetry(task, ie)) {
              // if the task couldn't be re-queued, then there's
              // nothing left to do but drop it
              task.setDone(ie);
              if (logger.isLoggable(Level.WARNING)) {
                logger.logThrow(Level.WARNING, ie, "dropping " + "an interrupted task: {0}" + task);
              }
            }
          }
          // always re-throw the interruption
          throw ie;
        } catch (Throwable t) {
          // make sure the transaction was aborted
          if ((transaction != null) && (!transaction.isAborted())) {
            transaction.abort(t);
          }
          profileCollectorHandle.finishTask(task.getTryCount(), t);
          // some error occurred, so see if we should re-try
          if (!shouldRetry(task, t)) {
            // the task is not being re-tried
            task.setDone(t);
            return true;
          } else {
            // see if the re-try should be handed-off
            task.setRunning(false);
            if (handoffRetry(task, t)) {
              return false;
            }
          }
        }
      }
    } finally {
      // always restore the previous owner before leaving...
      ContextResolver.setTaskState(kernelContext, parent);
    }
  }
 public void testCommitActiveEmpty() throws Exception {
   handle.commit();
   assertCommitted();
 }
 /** Prints the test case, sets handle and txn */
 protected void setUp() {
   System.err.println("Testcase: " + getName());
   handle = coordinator.createTransaction(false);
   txn = handle.getTransaction();
 }
 public void testGetTransactionCommitted() throws Exception {
   txn.join(new DummyTransactionParticipant());
   handle.commit();
   handle.getTransaction();
 }
 public void testGetTransactionActive() {
   handle.getTransaction();
 }
 public void testGetTransactionAborted() {
   txn.join(new DummyTransactionParticipant());
   txn.abort(abortXcp);
   handle.getTransaction();
 }