Search in sources :

Example 1 with LocalServer

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);
}
Also used : LocalServer(com.arjuna.ats.jta.distributed.server.LocalServer) Xid(javax.transaction.xa.Xid) Transaction(javax.transaction.Transaction) TransactionManager(javax.transaction.TransactionManager) ArrayList(java.util.ArrayList) IsolatableServersClassLoader(com.arjuna.ats.jta.distributed.server.IsolatableServersClassLoader) RollbackException(javax.transaction.RollbackException)

Example 2 with LocalServer

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);
}
Also used : LocalServer(com.arjuna.ats.jta.distributed.server.LocalServer) Xid(javax.transaction.xa.Xid) XAResource(javax.transaction.xa.XAResource) Transaction(javax.transaction.Transaction) TransactionManager(javax.transaction.TransactionManager) IsolatableServersClassLoader(com.arjuna.ats.jta.distributed.server.IsolatableServersClassLoader) RollbackException(javax.transaction.RollbackException) Date(java.util.Date) Test(org.junit.Test)

Example 3 with LocalServer

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);
}
Also used : LocalServer(com.arjuna.ats.jta.distributed.server.LocalServer) Xid(javax.transaction.xa.Xid) XAResource(javax.transaction.xa.XAResource) Transaction(javax.transaction.Transaction) TransactionManager(javax.transaction.TransactionManager) IsolatableServersClassLoader(com.arjuna.ats.jta.distributed.server.IsolatableServersClassLoader) RollbackException(javax.transaction.RollbackException) Test(org.junit.Test)

Example 4 with LocalServer

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);
}
Also used : LocalServer(com.arjuna.ats.jta.distributed.server.LocalServer) Xid(javax.transaction.xa.Xid) XAResource(javax.transaction.xa.XAResource) XAException(javax.transaction.xa.XAException) Transaction(javax.transaction.Transaction) TransactionManager(javax.transaction.TransactionManager) IsolatableServersClassLoader(com.arjuna.ats.jta.distributed.server.IsolatableServersClassLoader) Test(org.junit.Test)

Example 5 with LocalServer

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")));
}
Also used : LocalServer(com.arjuna.ats.jta.distributed.server.LocalServer) InputStream(java.io.InputStream) Xid(javax.transaction.xa.Xid) XAResource(javax.transaction.xa.XAResource) Transaction(javax.transaction.Transaction) TransactionManager(javax.transaction.TransactionManager) IsolatableServersClassLoader(com.arjuna.ats.jta.distributed.server.IsolatableServersClassLoader) ExecuteException(org.jboss.byteman.rule.exception.ExecuteException) Test(org.junit.Test) BMScript(org.jboss.byteman.contrib.bmunit.BMScript)

Aggregations

IsolatableServersClassLoader (com.arjuna.ats.jta.distributed.server.IsolatableServersClassLoader)10 LocalServer (com.arjuna.ats.jta.distributed.server.LocalServer)10 Transaction (javax.transaction.Transaction)10 TransactionManager (javax.transaction.TransactionManager)10 Xid (javax.transaction.xa.Xid)10 XAResource (javax.transaction.xa.XAResource)8 Test (org.junit.Test)6 RollbackException (javax.transaction.RollbackException)4 ArrayList (java.util.ArrayList)2 InputStream (java.io.InputStream)1 Date (java.util.Date)1 XAException (javax.transaction.xa.XAException)1 BMScript (org.jboss.byteman.contrib.bmunit.BMScript)1 ExecuteException (org.jboss.byteman.rule.exception.ExecuteException)1