use of com.arjuna.ats.arjuna.coordinator.TransactionReaper in project narayana by jbosstm.
the class TransactionFactoryImple method createLocal.
/**
* This creates a local instance of a transaction control, but does not
* register it with the ORB. Either call its getControl method directly, or
* use the create method of the factory.
*/
public ControlImple createLocal(int time_out) throws SystemException {
if (jtsLogger.logger.isTraceEnabled()) {
jtsLogger.logger.trace("TransactionFactoryImple::createLocal ( " + time_out + " )");
}
try {
ControlImple tranControl = new ControlImple((Control) null, (ArjunaTransactionImple) null);
int theTimeout = time_out;
if (theTimeout == 0)
theTimeout = TxControl.getDefaultTimeout();
if (theTimeout > 0) {
/*
* Currently we do not remove controls from the list once they
* have terminated. We should to save time and space!
*/
TransactionReaper reaper = TransactionReaper.transactionReaper();
reaper.insert(new ControlWrapper((ControlImple) tranControl), theTimeout);
}
return tranControl;
} catch (OutOfMemoryError e) {
/*
* Rather than try again after running gc simply return and let the
* user deal with it. May help with memory!
*/
System.gc();
throw new NO_MEMORY(0, CompletionStatus.COMPLETED_NO);
}
}
use of com.arjuna.ats.arjuna.coordinator.TransactionReaper in project narayana by jbosstm.
the class ReaperTestCase3 method testReaperForce.
@Test
public void testReaperForce() throws Exception {
TransactionReaper reaper = TransactionReaper.transactionReaper();
// give the reaper worker time to start too
Thread.sleep(1000);
// create test reapables some of which will not respond immediately to cancel requests
Uid uid0 = new Uid();
Uid uid1 = new Uid();
Uid uid2 = new Uid();
Uid uid3 = new Uid();
// reapable0 will return CANCELLED from cancel and will rendezvous inside the cancel call
// so we can delay it. prevent_commit should not get called so we don't care about the arguments
TestReapable reapable0 = new TestReapable(uid0, true, false, false, false);
// reapable1 will return CANCELLED from cancel and will not rendezvous inside the cancel call
// prevent_commit should not get called so we don't care about the arguments
TestReapable reapable1 = new TestReapable(uid1, true, false, false, false);
// reapable2 will return CANCELLED from cancel and will not rendezvous inside the cancel call
// prevent_commit should not get called so we don't care about the arguments
TestReapable reapable2 = new TestReapable(uid2, true, false, false, false);
// reapable3 will return CANCELLED from cancel and will not rendezvous inside the cancel call
// prevent_commit should not get called so we don't care about the arguments
TestReapable reapable3 = new TestReapable(uid3, true, false, false, false);
// enable a repeatable rendezvous before checking the reapable queue
enableRendezvous("reaper1", true);
// enable a repeatable rendezvous before processing a timed out reapable
// enableRendezvous("reaper2", true);
// enable a repeatable rendezvous before scheduling a reapable in the worker queue for cancellation
// enableRendezvous("reaper3", true);
// enable a repeatable rendezvous before rescheduling a reapable in the worker queue for cancellation
// enableRendezvous("reaper4", true);
// enable a repeatable rendezvous before interrupting a cancelled reapable
// enableRendezvous("reaper5", true);
// enable a repeatable rendezvous before marking a worker thread as a zombie
// enableRendezvous("reaper6", true);
// enable a repeatable rendezvous before marking a reapable as rollback only from the reaper thread
// enableRendezvous("reaper7", true);
// enable a repeatable rendezvous before checking the worker queue
enableRendezvous("reaperworker1", true);
// enable a repeatable rendezvous before marking a reapable as cancel
// enableRendezvous("reaperworker2", true);
// enable a repeatable rendezvous before calling cancel
// enableRendezvous("reaperworker3", true);
// enable a repeatable rendezvous before marking a reapable as rollback only from the worker thread
// enableRendezvous("reaperworker4", true);
// enable a repeatable rendezvous for each of the test reapables which we have marked to
// perform a rendezvous
// enableRendezvous(uid0, true);
reaper.insert(reapable0, 1);
reaper.insert(reapable1, 2);
reaper.insert(reapable2, 3);
reaper.insert(reapable3, 4);
// latch the reaper before it checks the queue
triggerRendezvous("reaper1");
// make sure they were all registered
assertEquals(4, reaper.numberOfTransactions());
assertEquals(4, reaper.numberOfTimeouts());
// ensure the first reapable is ready
triggerWait(1000);
// let the reaper process the first reapable then latch it again before it checks the queue
triggerRendezvous("reaper1");
triggerRendezvous("reaper1");
// latch the worker before it checks the worker queue
triggerRendezvous("reaperworker1");
// let the worker process the first reapable then latch it again before it checks the queue
triggerRendezvous("reaperworker1");
triggerRendezvous("reaperworker1");
// force a termination and don't wait for the normal timeout periods
// byteman rules will ensure that the reaper and reaperworker rendezvous gte deleted
// under this call
TransactionReaper.terminate(false);
assertEquals(0, reaper.numberOfTransactions());
assertTrue(reapable0.getCancelTried());
assertTrue(reapable1.getCancelTried());
assertTrue(reapable2.getCancelTried());
assertTrue(reapable3.getCancelTried());
/*
* Since we've (hopefully) just run two tests with new reapers in the same VM
* we've also shown that it's possible to start/terminate/start again!
*/
}
use of com.arjuna.ats.arjuna.coordinator.TransactionReaper in project narayana by jbosstm.
the class ReaperMonitorTest method test.
@Test
public void test() {
TransactionReaper reaper = TransactionReaper.transactionReaper();
DummyMonitor listener = new DummyMonitor();
reaper.addListener(listener);
AtomicAction A = new AtomicAction();
A.begin();
/*
* the reaper byteman script will make sure we synchronize with the reaper after this call
* just before it schedules the reapable for processing. the timout in the check method is
* there in case something is really wrong and the reapable does not get cancelled
*/
reaper.insert(A, 1);
assertTrue(listener.checkSucceeded(30 * 1000));
assertTrue(reaper.removeListener(listener));
// insert a new transaction with a longer timeout and check that we can find the remaining time
A = new AtomicAction();
reaper.insert(A, 1000);
long remaining = reaper.getRemainingTimeoutMills(A);
assertTrue(remaining != 0);
// ok now remove it
reaper.remove(A);
}
use of com.arjuna.ats.arjuna.coordinator.TransactionReaper in project narayana by jbosstm.
the class ReaperTestCase2 method testReaper.
@Test
public void testReaper() throws Exception {
TransactionReaper reaper = TransactionReaper.transactionReaper();
// create slow reapables some of which will not respond immediately
// to cancel requests and ensure that they get cancelled
// and that the reaper does not get wedged
// the rendezvous for the reapables are keyed by the reapable's uid
Uid uid0 = new Uid();
Uid uid1 = new Uid();
Uid uid2 = new Uid();
Uid uid3 = new Uid();
// reapable0 will return CANCELLED from cancel and will rendezvous inside the cancel call
// so we can delay it. prevent_commit should not get called so we don't care about the arguments
TestReapable reapable0 = new TestReapable(uid0, true, true, false, false);
// reapable1 will return CANCELLED from cancel and will not rendezvous inside the cancel call
// prevent_commit should not get called so we don't care about the arguments
TestReapable reapable1 = new TestReapable(uid1, true, false, false, false);
// reapable2 will return RUNNING from cancel and will rendezvous inside the cancel call
// the call will get delayed causing the worker to exit as a zombie
// prevent_commit will be called from the reaper thread and will fail but will not rendezvous
TestReapable reapable2 = new TestReapable(uid2, false, true, false, false);
// reapable3 will return RUNNING from cancel and will not rendezvous inside the cancel call
// prevent_commit should get called and should return true without a rendezvous
TestReapable reapable3 = new TestReapable(uid3, false, false, true, false);
// enable a repeatable rendezvous before checking the reapable queue
enableRendezvous("reaper1", true);
// enable a repeatable rendezvous when synchronizing on a timed out reapoer element so we can check that
// the element is the one we expect.
enableRendezvous("reaper element", true);
// enable a repeatable rendezvous before processing a timed out reapable
// enableRendezvous("reaper2", true);
// enable a repeatable rendezvous before scheduling a reapable in the worker queue for cancellation
// enableRendezvous("reaper3", true);
// enable a repeatable rendezvous before rescheduling a reapable in the worker queue for cancellation
// enableRendezvous("reaper4", true);
// enable a repeatable rendezvous before interrupting a cancelled reapable
// enableRendezvous("reaper5", true);
// enable a repeatable rendezvous before marking a worker thread as a zombie
// enableRendezvous("reaper6", true);
// enable a repeatable rendezvous before marking a reapable as rollback only from the reaper thread
// enableRendezvous("reaper7", true);
// enable a repeatable rendezvous before checking the worker queue
enableRendezvous("reaperworker1", true);
// enable a repeatable rendezvous before marking a reapable as cancel
// enableRendezvous("reaperworker2", true);
// enable a repeatable rendezvous before calling cancel
// enableRendezvous("reaperworker3", true);
// enable a repeatable rendezvous before marking a reapable as rollback only from the worker thread
// enableRendezvous("reaperworker4", true);
// enable a repeatable rendezvous for each of the test reapables which we have marked to
// perform a rendezvous
enableRendezvous(uid0, true);
enableRendezvous(uid2, true);
// STAGE I
// insert two reapables so they timeout at 1 second intervals then stall the first one and
// check progress of cancellations and rollbacks for both
reaper.insert(reapable0, 1);
reaper.insert(reapable1, 1);
// assertTrue(reaper.insert(reapable2, 1));
// assertTrue(reaper.insert(reapable3, 1));
// latch the reaper before it tries to process the queue
triggerRendezvous("reaper1");
// make sure they were all registered
// the transactions queue should be
// UID0 RUNNING
// UID1 RUNNING
assertEquals(2, reaper.numberOfTransactions());
assertEquals(2, reaper.numberOfTimeouts());
// wait long enough to ensure both reapables have timed out
triggerWait(1000);
// now let the reaper dequeue the first reapable, process it and queue it for the worker thread
// to deal with
triggerRendezvous("reaper1");
// latch the reaper at the reaper element check
triggerRendezvous("reaper element");
// check that we have dequeued reapable0
assertTrue(checkAndClearFlag(reapable0));
// unlatch the reaper so it can process the element
triggerRendezvous("reaper element");
// latch the reaper before it tests the queue again
triggerRendezvous("reaper1");
// latch the reaperworker before it tries to dequeue from the worker queue
triggerRendezvous("reaperworker1");
// the transactions queue should be
// UID1 RUNNING
// UID0 CANCEL
assertEquals(2, reaper.numberOfTransactions());
assertEquals(2, reaper.numberOfTimeouts());
// now let the worker dequeue a reapable and proceed to call cancel
triggerRendezvous("reaperworker1");
// latch the first reapable inside cancel
triggerRendezvous(uid0);
// now let the reaper check the queue for the second reapable, dequeue it and add it to the
// worker queue
triggerRendezvous("reaper1");
// latch the reaper at the reaper element check
triggerRendezvous("reaper element");
// check that we have dequeued reapable1
assertTrue(checkAndClearFlag(reapable1));
// unlatch the reaper so it can process the element
triggerRendezvous("reaper element");
// latch the reaper before it tests the queue again
triggerRendezvous("reaper1");
// the transactions queue should be
// UID0 CANCEL
// UID1 SCHEDULE_CANCEL
assertEquals(2, reaper.numberOfTransactions());
assertEquals(2, reaper.numberOfTimeouts());
// ensure we wait long enough for the cancel to time out
triggerWait(500);
// now let the reaper check the queue and interrupt the cancel for UID1
triggerRendezvous("reaper1");
// latch the reaper at the reaper element check
triggerRendezvous("reaper element");
// check that we have dequeued reapable0
assertTrue(checkAndClearFlag(reapable0));
// unlatch the reaper so it can process the element
triggerRendezvous("reaper element");
// latch the reaper before it tests the queue again
triggerRendezvous("reaper1");
// unlatch the first reapable inside cancel
triggerRendezvous(uid0);
// latch the worker as it is about to process the queue again
triggerRendezvous("reaperworker1");
// the transactions queue should be
// UID1 SCHEDULE_CANCEL
assertEquals(1, reaper.numberOfTransactions());
assertEquals(1, reaper.numberOfTimeouts());
// let the worker clear and cancel the 2nd reapable
triggerRendezvous("reaperworker1");
// latch the worker before it reads the worker queue
triggerRendezvous("reaperworker1");
// the transactions queue should be empty
assertEquals(0, reaper.numberOfTransactions());
assertEquals(0, reaper.numberOfTimeouts());
// ensure that cancel was tried on reapable1 and that set rollback only was not tried on either
// we know cancel was tried on reapable0 because we got through the rendezvous
assertTrue(reapable1.getCancelTried());
assertTrue(!reapable0.getRollbackTried());
assertTrue(!reapable1.getRollbackTried());
assertTrue(checkAndClearFlag("interrupted"));
// STAGE II
// now use the next pair of reapables to check that a wedged reaperworker gets tuirned into a zombie and
// a new worker gets created to cancel the remaining reapables.
// insert reapables so they timeout at 1 second intervals then
// check progress of cancellations and rollbacks
reaper.insert(reapable2, 1);
reaper.insert(reapable3, 1);
// make sure they were all registered
// the transactions queue should be
// UID2 RUNNING
// UID3 RUNNING
assertEquals(2, reaper.numberOfTransactions());
assertEquals(2, reaper.numberOfTimeouts());
// wait long enough to ensure both reapables have timed out
triggerWait(1000);
// now let the reaper dequeue the first reapable, process it and queue it for the worker thread
// to deal with
triggerRendezvous("reaper1");
// latch the reaper at the reaper element check
triggerRendezvous("reaper element");
// check that we have dequeued reapable2
assertTrue(checkAndClearFlag(reapable2));
// unlatch the reaper so it can process the element
triggerRendezvous("reaper element");
// latch the reaper before it tests the queue again
triggerRendezvous("reaper1");
// the transactions queue should be
// UID3 RUNNING
// UID2 CANCEL
assertEquals(2, reaper.numberOfTransactions());
assertEquals(2, reaper.numberOfTimeouts());
// now let the worker dequeue the fourth reapable and proceed to call cancel
triggerRendezvous("reaperworker1");
// latch the third reapable inside cancel
triggerRendezvous(uid2);
// now let the reaper check the queue for the fourth reapable, dequeue it and add it to the
// worker queue
triggerRendezvous("reaper1");
// latch the reaper at the reaper element check
triggerRendezvous("reaper element");
// check that we have dequeued reapable3
assertTrue(checkAndClearFlag(reapable3));
// unlatch the reaper so it can process the element
triggerRendezvous("reaper element");
// latch the reaper before it tests the queue again
triggerRendezvous("reaper1");
// the transactions queue should be
// UID2 CANCEL
// UID3 SCHEDULE_CANCEL
assertEquals(2, reaper.numberOfTransactions());
assertEquals(2, reaper.numberOfTimeouts());
// ensure we wait long enough for the cancel to time out
triggerWait(500);
// now let the reaper check the queue and interrupt the cancel for UID3
triggerRendezvous("reaper1");
// latch the reaper at the reaper element check
triggerRendezvous("reaper element");
// check that we have dequeued reapable2
assertTrue(checkAndClearFlag(reapable2));
// unlatch the reaper so it can process the element
triggerRendezvous("reaper element");
// latch the reaper before it tests the queue again
triggerRendezvous("reaper1");
assertTrue(checkAndClearFlag("interrupted"));
// ensure we wait long enough for the cancel to time out
triggerWait(500);
// the transactions queue should be
// UID3 SCHEDULE_CANCEL
// UID2 CANCEL_INTERRUPTED
assertEquals(2, reaper.numberOfTransactions());
assertEquals(2, reaper.numberOfTimeouts());
// let the reaper check the queue and reschedule the fourth reapable
triggerRendezvous("reaper1");
// latch the reaper at the reaper element check
triggerRendezvous("reaper element");
// check that we have dequeued reapable3
assertTrue(checkAndClearFlag(reapable3));
// unlatch the reaper so it can process the element
triggerRendezvous("reaper element");
// latch the reaper before it tests the queue again
triggerRendezvous("reaper1");
// the transactions queue should be
// UID2 CANCEL_INTERRUPTED
// UID3 SCHEDULE_CANCEL
assertEquals(2, reaper.numberOfTransactions());
assertEquals(2, reaper.numberOfTimeouts());
// let the reaper check the queue and mark the reaper worker as a zombie
triggerRendezvous("reaper1");
// latch the reaper at the reaper element check
triggerRendezvous("reaper element");
// check that we have dequeued reapable2
assertTrue(checkAndClearFlag(reapable2));
// unlatch the reaper so it can process the element
triggerRendezvous("reaper element");
// latch the reaper before it tests the queue again
triggerRendezvous("reaper1");
// the reaper should have marked the thread as a zombie
assertTrue(checkAndClearFlag("zombied"));
// the transactions queue should be
// UID3 SCHEDULE_CANCEL
assertEquals(1, reaper.numberOfTransactions());
assertEquals(1, reaper.numberOfTimeouts());
// unlatch the third reapable inside cancel
triggerRendezvous(uid2);
// latch the new worker as it is about to process the queue again
triggerRendezvous("reaperworker1");
// let the worker clear and cancel the 2nd reapable
triggerRendezvous("reaperworker1");
// latch the worker before it reads the worker queue
triggerRendezvous("reaperworker1");
// the transactions queue should be empty
assertEquals(0, reaper.numberOfTransactions());
assertEquals(0, reaper.numberOfTimeouts());
// ensure that cancel was tried on reapable3 and that set rollback only was tried on reapable2
// and reapable3 we know cancel was tried on reapable2 because we got through the rendezvous
assertTrue(reapable3.getCancelTried());
assertTrue(reapable2.getRollbackTried());
assertTrue(reapable3.getRollbackTried());
}
use of com.arjuna.ats.arjuna.coordinator.TransactionReaper in project narayana by jbosstm.
the class ReaperTestCase method testReaper.
@Test
public void testReaper() throws Exception {
TransactionReaper reaper = TransactionReaper.transactionReaper();
Reapable reapable = new MockReapable(new Uid());
Reapable reapable2 = new MockReapable(new Uid());
Reapable reapable3 = new MockReapable(new Uid());
ReaperElement reaperElement = new ReaperElement(reapable, 30);
ReaperElement reaperElement2 = new ReaperElement(reapable2, 20);
ReaperElement reaperElement3 = new ReaperElement(reapable3, 10);
// test that ordering is by timeout, regardless of insertion order
SortedSet sortedSet = new TreeSet();
sortedSet.add(reaperElement);
sortedSet.add(reaperElement3);
sortedSet.add(reaperElement2);
assertEquals(sortedSet.first(), reaperElement3);
assertEquals(sortedSet.last(), reaperElement);
// test insertion of timeout=0 is a nullop
reaper.insert(reapable, 0);
assertEquals(0, reaper.numberOfTransactions());
assertEquals(0, reaper.numberOfTimeouts());
reaper.remove(reapable);
// test that duplicate insertion fails
reaper.insert(reapable, 10);
assertEquals(1, reaper.numberOfTransactions());
assertEquals(1, reaper.numberOfTimeouts());
try {
reaper.insert(reapable, 10);
fail("duplicate insert failed to blow up");
} catch (Exception e) {
}
reaper.remove(reapable);
assertEquals(0, reaper.numberOfTransactions());
assertEquals(0, reaper.numberOfTimeouts());
// test that timeout change fails
reaper.insert(reapable, 10);
try {
reaper.insert(reapable, 20);
fail("timeout change insert failed to blow up");
} catch (Exception e) {
}
assertEquals(1, reaper.numberOfTransactions());
assertEquals(1, reaper.numberOfTimeouts());
assertEquals(10, reaper.getTimeout(reapable));
reaper.remove(reapable);
assertEquals(0, reaper.numberOfTransactions());
assertEquals(0, reaper.numberOfTimeouts());
// enable a repeatable rendezvous before checking the reapable queue
enableRendezvous("reaper1", true);
// enable a repeatable rendezvous before scheduling a reapable in the worker queue for cancellation
enableRendezvous("reaper2", true);
// enable a repeatable rendezvous before checking the worker queue
enableRendezvous("reaperworker1", true);
// test reaping
// seconds
reaper.insert(reapable, 1);
reaper.insert(reapable2, 2);
// the reaper will be latched before it processes any of the reapables
triggerRendezvous("reaper1");
assertEquals(2, reaper.numberOfTransactions());
assertEquals(2, reaper.numberOfTimeouts());
// ensure we have waited at lest 1 second so the first reapable is timed out
triggerWait(1000);
// let the reaper proceed with the dequeue and add the entry to the work queue
triggerRendezvous("reaper1");
triggerRendezvous("reaper2");
triggerRendezvous("reaper2");
// now latch the reaper worker at the dequeue
triggerRendezvous("reaperworker1");
// we shoudl still have two reapables in the reaper queue
assertEquals(2, reaper.numberOfTransactions());
assertEquals(2, reaper.numberOfTimeouts());
// now let the worker process the work queue element -- it should not call cancel since the
// mock reapable will not claim to be running
triggerRendezvous("reaperworker1");
// latch the reaper and reaper worker before they check their respective queues
// latch the reaper before it dequeues the next reapable
triggerRendezvous("reaper1");
triggerRendezvous("reaperworker1");
// we should now have only 1 element in the reaper queue
assertEquals(1, reaper.numberOfTransactions());
assertEquals(1, reaper.numberOfTimeouts());
// ensure we have waited at lest 1 second so the second reapable is timed out
triggerWait(1000);
// now let the reaper proceed with the next dequeue and enqueue the reapable for the worker to process
triggerRendezvous("reaper1");
triggerRendezvous("reaper2");
triggerRendezvous("reaper2");
// relatch the reaper next time round the loop so we can be sure it is not monkeying around
// with the transactions queue
triggerRendezvous("reaper1");
// the worker is still latched so we should still have one entry in the work queue
assertEquals(1, reaper.numberOfTransactions());
assertEquals(1, reaper.numberOfTimeouts());
// now let the worker process the work queue element -- it should not call cancel since the
// mock reapable wil not claim to be running
triggerRendezvous("reaperworker1");
// latch reaper worker again so we know it has finished processing the element
triggerRendezvous("reaperworker1");
assertEquals(0, reaper.numberOfTransactions());
assertEquals(0, reaper.numberOfTimeouts());
}
Aggregations