use of org.jboss.byteman.rule.exception.ExecuteException in project narayana by jbosstm.
the class TestCommitMarkableResourceFailAfterCommitOrphan method test.
@Test
@BMScript("commitMarkableResourceFailAfterCommit")
public void test() throws Exception {
final JdbcDataSource dataSource = new JdbcDataSource();
dataSource.setURL("jdbc:h2:mem:JBTMDB;MVCC=TRUE;DB_CLOSE_DELAY=-1");
// Test code
Utils.createTables(dataSource.getConnection());
// We can't just instantiate one as we need to be using the
// same one as
// the transaction
// manager would have used to mark the transaction for GC
CommitMarkableResourceRecordRecoveryModule commitMarkableResourceRecoveryModule = null;
Vector recoveryModules = manager.getModules();
if (recoveryModules != null) {
Enumeration modules = recoveryModules.elements();
while (modules.hasMoreElements()) {
RecoveryModule m = (RecoveryModule) modules.nextElement();
if (m instanceof CommitMarkableResourceRecordRecoveryModule) {
commitMarkableResourceRecoveryModule = (CommitMarkableResourceRecordRecoveryModule) m;
} else if (m instanceof XARecoveryModule) {
xarm = (XARecoveryModule) m;
xarm.addXAResourceRecoveryHelper(new XAResourceRecoveryHelper() {
public boolean initialise(String p) throws Exception {
return true;
}
public XAResource[] getXAResources() throws Exception {
return new XAResource[] { xaResource };
}
});
}
}
}
// final Object o = new Object();
// synchronized (o) {
Thread preCrash = new Thread(new Runnable() {
public void run() {
try (Connection localJDBCConnection = dataSource.getConnection()) {
javax.transaction.TransactionManager tm = com.arjuna.ats.jta.TransactionManager.transactionManager();
tm.begin();
localJDBCConnection.setAutoCommit(false);
cmrResource = new JDBCConnectableResource(localJDBCConnection);
tm.getTransaction().enlistResource(cmrResource);
tm.getTransaction().enlistResource(xaResource);
localJDBCConnection.createStatement().execute("INSERT INTO foo (bar) VALUES (1)");
tm.commit();
} catch (ExecuteException t) {
} catch (Exception e) {
e.printStackTrace();
failed = true;
} catch (Error e) {
}
}
});
preCrash.start();
preCrash.join();
assertFalse(failed);
assertFalse(wasCommitted);
assertFalse(wasRolledback);
// The recovery module has to perform lookups
new InitialContext().rebind("commitmarkableresource", dataSource);
// Testing that we can find a AAC but that it won't be ignored in orphan detection so need CMRRM run
commitMarkableResourceRecoveryModule.periodicWorkFirstPass();
XAResourceOrphanFilter.Vote vote = new JTATransactionLogXAResourceOrphanFilter().checkXid(preparedXid);
assertTrue(vote == XAResourceOrphanFilter.Vote.LEAVE_ALONE);
manager.scan();
manager.scan();
assertTrue(wasCommitted);
}
use of org.jboss.byteman.rule.exception.ExecuteException in project narayana by jbosstm.
the class SimpleIsolatedServers method testSimultaneousRecover.
/**
* Ensure that two servers can start up and call recover on the same server
*
* The JCA XATerminator call wont allow intermediary calls to
* XATerminator::recover between TMSTARTSCAN and TMENDSCAN. This is fine for
* distributed JTA.
*
* @throws XAException
* @throws IOException
* @throws DummyRemoteException
*/
@Test
@BMScript("leave-subordinate-orphan")
public void testSimultaneousRecover() throws Exception {
System.out.println("testSimultaneousRecover");
assertTrue("" + completionCounter.getCommitCount("2000"), completionCounter.getCommitCount("2000") == 0);
assertTrue("" + completionCounter.getRollbackCount("2000"), completionCounter.getRollbackCount("2000") == 0);
assertTrue("" + completionCounter.getCommitCount("1000"), completionCounter.getCommitCount("1000") == 0);
assertTrue("" + completionCounter.getRollbackCount("1000"), completionCounter.getRollbackCount("1000") == 0);
final CompletionCountLock phase2CommitAborted = new CompletionCountLock();
synchronized (phase2CommitAborted) {
{
Thread thread = new Thread(new Runnable() {
public void run() {
int startingTimeout = 0;
try {
LocalServer originalServer = getLocalServer("1000");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(originalServer.getClassLoader());
TransactionManager transactionManager = originalServer.getTransactionManager();
transactionManager.setTransactionTimeout(startingTimeout);
transactionManager.begin();
Transaction originalTransaction = transactionManager.getTransaction();
int remainingTimeout = (int) (originalServer.getTimeLeftBeforeTransactionTimeout() / 1000);
Xid currentXid = originalServer.getCurrentXid();
transactionManager.suspend();
DataReturnedFromRemoteServer performTransactionalWork = performTransactionalWork(new LinkedList<String>(Arrays.asList(new String[] { "2000" })), remainingTimeout, currentXid, 2, false, false);
transactionManager.resume(originalTransaction);
XAResource proxyXAResource = originalServer.generateProxyXAResource("2000", performTransactionalWork.getProxyRequired());
originalTransaction.enlistResource(proxyXAResource);
transactionManager.commit();
Thread.currentThread().setContextClassLoader(classLoader);
synchronized (phase2CommitAborted) {
phase2CommitAborted.notify();
}
} catch (ExecuteException e) {
System.err.println("Should be a thread death but cest la vie");
synchronized (phase2CommitAborted) {
phase2CommitAborted.incrementCount();
phase2CommitAborted.notify();
}
} catch (LinkageError t) {
System.err.println("Should be a thread death but cest la vie");
synchronized (phase2CommitAborted) {
phase2CommitAborted.incrementCount();
phase2CommitAborted.notify();
}
} catch (Throwable t) {
System.err.println("Should be a thread death but cest la vie");
synchronized (phase2CommitAborted) {
phase2CommitAborted.incrementCount();
phase2CommitAborted.notify();
}
}
}
}, "Orphan-creator");
thread.start();
}
{
Thread thread = new Thread(new Runnable() {
public void run() {
int startingTimeout = 0;
try {
LocalServer originalServer = getLocalServer("2000");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(originalServer.getClassLoader());
TransactionManager transactionManager = originalServer.getTransactionManager();
transactionManager.setTransactionTimeout(startingTimeout);
transactionManager.begin();
Transaction originalTransaction = transactionManager.getTransaction();
int remainingTimeout = (int) (originalServer.getTimeLeftBeforeTransactionTimeout() / 1000);
Xid currentXid = originalServer.getCurrentXid();
transactionManager.suspend();
DataReturnedFromRemoteServer performTransactionalWork = performTransactionalWork(new LinkedList<String>(Arrays.asList(new String[] { "1000" })), remainingTimeout, currentXid, 2, false, false);
transactionManager.resume(originalTransaction);
XAResource proxyXAResource = originalServer.generateProxyXAResource("1000", performTransactionalWork.getProxyRequired());
originalTransaction.enlistResource(proxyXAResource);
transactionManager.commit();
Thread.currentThread().setContextClassLoader(classLoader);
synchronized (phase2CommitAborted) {
phase2CommitAborted.notify();
}
} catch (ExecuteException e) {
System.err.println("Should be a thread death but cest la vie");
synchronized (phase2CommitAborted) {
phase2CommitAborted.incrementCount();
phase2CommitAborted.notify();
}
} catch (LinkageError t) {
System.err.println("Should be a thread death but cest la vie");
synchronized (phase2CommitAborted) {
phase2CommitAborted.incrementCount();
phase2CommitAborted.notify();
}
} catch (Throwable t) {
System.err.println("Should be a thread death but cest la vie");
synchronized (phase2CommitAborted) {
phase2CommitAborted.incrementCount();
phase2CommitAborted.notify();
}
}
}
}, "Orphan-creator");
thread.start();
}
int waitedCount = 0;
while (waitedCount < 2) {
phase2CommitAborted.wait(50000);
waitedCount++;
if (waitedCount == 2 && phase2CommitAborted.getCount() < 2) {
fail("Servers were not aborted");
}
}
}
reboot("1000");
reboot("2000");
reboot("3000");
final CompletionCountLock lock = new CompletionCountLock();
{
new Thread(new Runnable() {
public void run() {
getLocalServer("2000").doRecoveryManagerScan(true);
lock.incrementCount();
}
}, "RecMan2000").start();
}
{
new Thread(new Runnable() {
public void run() {
getLocalServer("1000").doRecoveryManagerScan(true);
lock.incrementCount();
}
}, "RecMan1000").start();
}
synchronized (lock) {
while (lock.getCount() < 2) {
lock.wait(300000);
}
if (lock.getCount() < 2) {
fail("Did not get notification for both recovery runs, deadlock in recovery manager scan detected");
ProcessBuilder processBuilder = new ProcessBuilder("/bin/sh", "-c", "kill -3 $PPID");
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
InputStream inputStream = process.getInputStream();
final byte[] bytes = new byte[4096];
int bytesRead = inputStream.read(bytes);
while (bytesRead > -1) {
System.out.write(bytes, 0, bytesRead);
bytesRead = inputStream.read(bytes);
}
}
}
assertTrue("" + completionCounter.getCommitCount("1000"), completionCounter.getCommitCount("1000") == 0);
// JBTM-1260 simultaneous recover can cause spurious Xid rollback of normally completed Xid, should not be an issue
// JBTM-1345 simulatenous recover can cause spurious Xid rollback of completed resources, should not be a data integrity issue
assertTrue("" + completionCounter.getRollbackCount("1000"), Arrays.asList(new Integer[] { 3, 4, 5 }).contains(completionCounter.getRollbackCount("1000")));
assertTrue("" + completionCounter.getCommitCount("2000"), completionCounter.getCommitCount("2000") == 0);
assertTrue("" + completionCounter.getRollbackCount("2000"), Arrays.asList(new Integer[] { 3, 4, 5 }).contains(completionCounter.getRollbackCount("2000")));
}
Aggregations