@Override public TransactionStatus getStatus() { try { EmbeddedTransaction transaction = tm.getTransaction(); return transaction == null ? TransactionStatus.NOT_ACTIVE : StatusTranslator.translate(transaction.getStatus()); } catch (SystemException e) { throw new RuntimeException(e); } }
public void testReplay() throws Exception { assertClusterSize("Wrong cluster size", 3); final Object key = new MagicKey(cache(0), cache(1)); final Cache<Object, Object> newBackupOwnerCache = cache(2); final TxCommandInterceptor interceptor = TxCommandInterceptor.inject(newBackupOwnerCache); EmbeddedTransactionManager transactionManager = (EmbeddedTransactionManager) tm(0); transactionManager.begin(); cache(0).put(key, VALUE); final EmbeddedTransaction transaction = transactionManager.getTransaction(); transaction.runPrepare(); assertEquals("Wrong transaction status before killing backup owner.", Status.STATUS_PREPARED, transaction.getStatus()); //now, we kill cache(1). the transaction is prepared in cache(1) and it should be forward to cache(2) killMember(1); checkIfTransactionExists(newBackupOwnerCache); assertEquals("Wrong transaction status after killing backup owner.", Status.STATUS_PREPARED, transaction.getStatus()); transaction.runCommit(false); assertNoTransactions(); assertEquals("Wrong number of prepares!", 1, interceptor.numberPrepares.get()); assertEquals("Wrong number of commits!", 1, interceptor.numberCommits.get()); assertEquals("Wrong number of rollbacks!", 0, interceptor.numberRollbacks.get()); checkKeyInDataContainer(key); }
private void performTest(Operation operation) throws Exception { assertClusterSize("Wrong number of caches.", 4); final Object key = new MagicKey(cache(0), cache(1), cache(2)); //init operation.init(cache(0), key); final EmbeddedTransactionManager transactionManager = (EmbeddedTransactionManager) tm(0); transactionManager.begin(); operation.perform(cache(0), key); final EmbeddedTransaction transaction = transactionManager.getTransaction(); transaction.runPrepare(); assertEquals("Wrong transaction status before killing backup owner.", Status.STATUS_PREPARED, transaction.getStatus()); //now, we kill cache(1). the transaction is prepared in cache(1) and it should be forward to cache(3) killMember(1); assertEquals("Wrong transaction status after killing backup owner.", Status.STATUS_PREPARED, transaction.getStatus()); transaction.runCommit(false); for (Cache<Object, Object> cache : caches()) { //all the caches are owner operation.check(cache, key, valueOf(address(cache))); } }
public void testPrimaryOwnerCrash() throws Exception { // cache 0 is the originator and backup, cache 1 is the primary owner StateSequencer ss = new StateSequencer(); ss.logicalThread("main", "block_prepare", "crash_primary", "resume_prepare"); tm(0).begin(); cache(0).put("k", "v1"); EmbeddedTransaction tx1 = (EmbeddedTransaction) tm(0).suspend(); tx1.runPrepare(); advanceOnInboundRpc(ss, cache(1), matchCommand(VersionedPrepareCommand.class).build()) .before("block_prepare", "resume_prepare"); Future<EmbeddedTransaction> tx2Future = fork(() -> { tm(0).begin(); cache(0).put("k", "v2"); EmbeddedTransaction tx2 = (EmbeddedTransaction) tm(0).suspend(); tx2.runPrepare(); return tx2; }); ss.enter("crash_primary"); killMember(1); ss.exit("crash_primary"); // tx2 prepare times out trying to acquire the lock, but does not throw an exception at this time EmbeddedTransaction tx2 = tx2Future.get(30, SECONDS); assertEquals(Status.STATUS_MARKED_ROLLBACK, tx2.getStatus()); Exceptions.expectException(RollbackException.class, XAException.class, TimeoutException.class, () -> tx2.runCommit(false)); // tx1 should commit successfully tx1.runCommit(false); }
transaction.runPrepare(); transaction.runCommit(forceRollback()); return transaction.getStatus(); });