use of com.arjuna.ats.jta.distributed.server.LocalServer in project narayana by jbosstm.
the class SimpleIsolatedServers method doRecursiveTransactionalWork.
private void doRecursiveTransactionalWork(int startingTimeout, List<String> nodesToFlowTo, boolean commit, boolean rollbackOnlyOnLastNode) throws Exception {
List<String> uniqueServers = new ArrayList<String>();
Iterator<String> iterator = nodesToFlowTo.iterator();
while (iterator.hasNext()) {
String intern = iterator.next().intern();
if (!uniqueServers.contains(intern)) {
uniqueServers.add(intern);
}
}
// Start out at the first server
int totalCompletionCount = nodesToFlowTo.size() + uniqueServers.size() - 1;
String startingServer = nodesToFlowTo.get(0);
LocalServer originalServer = getLocalServer(startingServer);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(originalServer.getClassLoader());
TransactionManager transactionManager = originalServer.getTransactionManager();
transactionManager.setTransactionTimeout(startingTimeout);
transactionManager.begin();
Transaction transaction = transactionManager.getTransaction();
int remainingTimeout = (int) (originalServer.getTimeLeftBeforeTransactionTimeout() / 1000);
Xid currentXid = originalServer.getCurrentXid();
transactionManager.suspend();
DataReturnedFromRemoteServer dataReturnedFromRemoteServer = performTransactionalWork(nodesToFlowTo, remainingTimeout, currentXid, 1, true, rollbackOnlyOnLastNode);
transactionManager.resume(transaction);
// from the subordinate
switch(dataReturnedFromRemoteServer.getTransactionState()) {
case Status.STATUS_MARKED_ROLLBACK:
case Status.STATUS_ROLLEDBACK:
case Status.STATUS_ROLLING_BACK:
switch(transaction.getStatus()) {
case Status.STATUS_MARKED_ROLLBACK:
case Status.STATUS_ROLLEDBACK:
case Status.STATUS_ROLLING_BACK:
transaction.setRollbackOnly();
}
break;
default:
break;
}
if (commit) {
try {
transactionManager.commit();
assertTrue(completionCounter.getTotalCommitCount() == totalCompletionCount);
} catch (RollbackException e) {
if (!rollbackOnlyOnLastNode) {
assertTrue(completionCounter.getTotalRollbackCount() == totalCompletionCount);
}
}
} else {
transactionManager.rollback();
assertTrue(completionCounter.getTotalRollbackCount() == totalCompletionCount);
}
Thread.currentThread().setContextClassLoader(classLoader);
}
use of com.arjuna.ats.jta.distributed.server.LocalServer in project narayana by jbosstm.
the class SimpleIsolatedServers method testMigrateTransactionParentTimeout.
@Test
public void testMigrateTransactionParentTimeout() throws Exception {
System.out.println("testMigrateTransactionParentTimeout");
tearDown();
setup();
int rootTimeout = 5;
// artificially high to ensure the timeout is performed by the parent
int subordinateTimeout = 10;
LocalServer originalServer = getLocalServer("1000");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(originalServer.getClassLoader());
TransactionManager transactionManager = originalServer.getTransactionManager();
transactionManager.setTransactionTimeout(rootTimeout);
transactionManager.begin();
Transaction originalTransaction = transactionManager.getTransaction();
Xid currentXid = originalServer.getCurrentXid();
originalTransaction.enlistResource(new TestResource(originalServer.getNodeName(), false));
transactionManager.suspend();
// Migrate a transaction
LocalServer currentServer = getLocalServer("2000");
ClassLoader parentsClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(currentServer.getClassLoader());
Xid migratedXid = currentServer.locateOrImportTransactionThenResumeIt(subordinateTimeout, currentXid);
currentServer.getTransactionManager().getTransaction().enlistResource(new TestResource(currentServer.getNodeName(), false));
currentServer.getTransactionManager().suspend();
Thread.currentThread().setContextClassLoader(parentsClassLoader);
// Complete the transaction at the original server
System.out.println(new Date() + " resuming");
transactionManager.resume(originalTransaction);
System.out.println(new Date() + " generating");
XAResource proxyXAResource = originalServer.generateProxyXAResource("2000", migratedXid);
System.out.println(new Date() + " enlisting");
originalTransaction.enlistResource(proxyXAResource);
System.out.println(new Date() + " sleeping");
Thread.sleep(rootTimeout * 2000);
try {
System.out.println(new Date() + " committing");
transactionManager.commit();
fail("Committed a transaction that should have rolled back");
} catch (RollbackException rbe) {
// This is OK
} finally {
Thread.currentThread().setContextClassLoader(classLoader);
}
assertTrue("" + completionCounter.getCommitCount("2000"), completionCounter.getCommitCount("2000") == 0);
assertTrue("" + completionCounter.getCommitCount("1000"), completionCounter.getCommitCount("1000") == 0);
assertTrue("" + completionCounter.getRollbackCount("2000"), completionCounter.getRollbackCount("2000") == 1);
assertTrue("" + completionCounter.getRollbackCount("1000"), completionCounter.getRollbackCount("1000") == 2);
}
use of com.arjuna.ats.jta.distributed.server.LocalServer in project narayana by jbosstm.
the class SimpleIsolatedServers method testMigrateTransactionSubordinateTimeout.
@Test
public void testMigrateTransactionSubordinateTimeout() throws Exception {
System.out.println("testMigrateTransactionSubordinateTimeout");
tearDown();
setup();
int rootTimeout = 10000;
// artificially low to ensure the timeout is performed by the subordinate
int subordinateTimeout = 1;
LocalServer originalServer = getLocalServer("1000");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(originalServer.getClassLoader());
TransactionManager transactionManager = originalServer.getTransactionManager();
transactionManager.setTransactionTimeout(rootTimeout);
transactionManager.begin();
Transaction originalTransaction = transactionManager.getTransaction();
Xid currentXid = originalServer.getCurrentXid();
originalTransaction.enlistResource(new TestResource(originalServer.getNodeName(), false));
transactionManager.suspend();
// Migrate a transaction
LocalServer currentServer = getLocalServer("2000");
ClassLoader parentsClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(currentServer.getClassLoader());
Xid migratedXid = currentServer.locateOrImportTransactionThenResumeIt(subordinateTimeout, currentXid);
currentServer.getTransactionManager().getTransaction().enlistResource(new TestResource(currentServer.getNodeName(), false));
currentServer.getTransactionManager().suspend();
Thread.currentThread().setContextClassLoader(parentsClassLoader);
// Complete the transaction at the original server
transactionManager.resume(originalTransaction);
XAResource proxyXAResource = originalServer.generateProxyXAResource("2000", migratedXid);
originalTransaction.enlistResource(proxyXAResource);
Thread.sleep((subordinateTimeout + 2) * 1000);
try {
transactionManager.commit();
fail("Did not rollback");
} catch (RollbackException rbe) {
// GOOD!
} finally {
Thread.currentThread().setContextClassLoader(classLoader);
}
assertTrue("" + completionCounter.getRollbackCount("2000"), completionCounter.getRollbackCount("2000") == 1);
assertTrue("" + completionCounter.getRollbackCount("1000"), completionCounter.getRollbackCount("1000") == 2);
}
use of com.arjuna.ats.jta.distributed.server.LocalServer in project narayana by jbosstm.
the class SimpleIsolatedServers method testDisabledDynamic1PC.
@Test
public void testDisabledDynamic1PC() throws Exception {
System.out.println("testDisabledDynamic1PC");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Transaction originalTransaction;
int remainingTimeout;
Xid toMigrate;
final boolean[] resource1prepared = new boolean[1];
{
LocalServer originalServer = getLocalServer("1000");
Thread.currentThread().setContextClassLoader(originalServer.getClassLoader());
TransactionManager transactionManager = originalServer.getTransactionManager();
transactionManager.setTransactionTimeout(0);
transactionManager.begin();
originalTransaction = transactionManager.getTransaction();
remainingTimeout = (int) (originalServer.getTimeLeftBeforeTransactionTimeout() / 1000);
toMigrate = originalServer.getCurrentXid();
transactionManager.suspend();
}
Xid requiresProxyAtPreviousServer = null;
{
LocalServer currentServer = getLocalServer("2000");
Thread.currentThread().setContextClassLoader(currentServer.getClassLoader());
currentServer.locateOrImportTransactionThenResumeIt(remainingTimeout, toMigrate);
// Perform work on the migrated transaction
{
TransactionManager transactionManager = currentServer.getTransactionManager();
Transaction transaction = transactionManager.getTransaction();
transaction.enlistResource(new TestResource(currentServer.getNodeName(), true));
transaction.enlistResource(new TestResource(currentServer.getNodeName(), false) {
@Override
public synchronized void commit(Xid id, boolean onePhase) throws XAException {
assertTrue(resource1prepared[0]);
super.commit(id, onePhase);
}
});
}
}
{
LocalServer originalServer = getLocalServer("1000");
TransactionManager transactionManager = originalServer.getTransactionManager();
transactionManager.resume(originalTransaction);
XAResource proxyXAResource = originalServer.generateProxyXAResource("2000", requiresProxyAtPreviousServer);
originalTransaction.enlistResource(proxyXAResource);
originalTransaction.enlistResource(new TestResource(originalServer.getNodeName(), false) {
@Override
public synchronized int prepare(Xid xid) throws XAException, Error {
resource1prepared[0] = true;
return super.prepare(xid);
}
});
transactionManager.commit();
}
Thread.currentThread().setContextClassLoader(classLoader);
assertTrue("" + completionCounter.getCommitCount("1000"), completionCounter.getCommitCount("1000") == 2);
assertTrue("" + completionCounter.getCommitCount("2000"), completionCounter.getCommitCount("2000") == 1);
assertTrue("" + completionCounter.getRollbackCount("2000"), completionCounter.getRollbackCount("2000") == 0);
assertTrue("" + completionCounter.getRollbackCount("1000"), completionCounter.getRollbackCount("1000") == 0);
}
use of com.arjuna.ats.jta.distributed.server.LocalServer 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