package com.hp.mwtests.ts.arjuna.reaper;
import com.arjuna.ats.arjuna.common.Uid;
import com.arjuna.ats.arjuna.coordinator.ActionStatus;
import com.arjuna.ats.arjuna.coordinator.Reapable;
/**
* class which provides control methods inherited by the reaper test classes. these methods can be
* used to enable, disable and trigger execution of byteman rules which regulate progress of the reaper
* and reaper worker thread as the reaper tests progress. they rely on the code being run in a JVM
* using the byteman agent with a suitable rule script which performs the desired actions when these
* methods are called. See script reaper.txt for the corresponding rules.
*/
public class ReaperTestCaseControl
{
/**
* called to enable a rendezvous with count 2. this method works by triggering a rule which calls
* Byteman helper builtin createRendezvous(o, 2, repeatable)
* @param o the key identifying the rendezvous
* @param repeatable whether the created rendezvous should be repeatable or not
*/
protected void enableRendezvous(Object o, boolean repeatable)
{
// do nothing this is just used for rule triggering
}
/**
* called to delete a rendezvous with count 2. this method works by triggering a rule which calls
* Byteman helper builtin deleteRendezvous(o, 2)
* @param o the key identifying the rendezvous
*/
protected void disableRendezvous(Object o)
{
// do nothing this is just used for rule triggering
}
/**
* called to trigger entry into a rendezvous with count 2. this method works by triggering a rule which
* calls Byteman helper builtin rendezvous(o). The assumption is that the code under test will also be
* trying to enter the rendezvous.
* @param o the key identifying the rendezvous
*/
protected void triggerRendezvous(Object o)
{
// do nothing this is just used for rule triggering
}
/**
* called to trigger a delay. this method works by triggering a rule which calls Byteman helper builtin
* delay(msecs).
* @param msecs the number of milliseconds for which the thread should delay
*/
protected void triggerWait(int msecs)
{
// do nothing this is just used for rule triggering
}
/**
* called to test a rule system flag and clear it at the same time. this method works by triggering a rule
* which calls Byteman helper builtin clear(o)
* @param o the key which identifies the rule system flag to be tested and cleared
*/
protected boolean checkAndClearFlag(Object o)
{
// return false by default -- rule system will intercept and return the relevant flag
// setting
return false;
}
/**
* reapable which can be controlled using rule actions driven by the test class
*/
public class TestReapable implements Reapable
{
/**
* create a mock reapable
* @param uid
* @param doCancel true if the reapable should return ABORTED from the cancel call and false if it should
* return RUNNING
* @param rendezvousInCancel true iff the reapable should rendezvous with the test code when cancel is called
* @param doRollback the value that the reapable should return true from the prevent_commit call
* @param rendezvousInInterrupt true iff the reapable should rendezvous with the test code when it is
*/
public TestReapable(Uid uid, boolean doCancel, boolean rendezvousInCancel, boolean doRollback, boolean rendezvousInInterrupt)
{
this.uid = uid;
this.rendezvousInCancel = rendezvousInCancel;
this.rendezvousInInterrupt = rendezvousInInterrupt;
this.doCancel = doCancel;
this.doRollback = doRollback;
cancelTried = false;
rollbackTried = false;
running = true;
}
public boolean running()
{
return getRunning();
}
public boolean preventCommit()
{
setRollbackTried();
if (rendezvousInInterrupt) {
triggerRendezvous(uid);
triggerRendezvous(uid);
}
clearRunning();
return doRollback;
}
public int cancel()
{
boolean interrupted = false;
setCancelTried();
// track the worker trying to do the cancel so we can
// detect if it becomes a zombie
setCancelThread(Thread.currentThread());
if (rendezvousInCancel) {
triggerRendezvous(uid);
triggerRendezvous(uid);
}
if (doCancel) {
clearRunning();
return ActionStatus.ABORTED;
} else {
return ActionStatus.RUNNING;
}
}
public Uid get_uid()
{
return uid;
}
private Uid uid;
private boolean doCancel;
private boolean doRollback;
private boolean rendezvousInCancel;
private boolean rendezvousInInterrupt;
private boolean cancelTried;
private boolean rollbackTried;
private boolean running;
private Thread cancelThread;
public synchronized void setCancelTried()
{
cancelTried = true;
}
public synchronized boolean getCancelTried()
{
return cancelTried;
}
public synchronized void setCancelThread(Thread cancelThread)
{
this.cancelThread = cancelThread;
}
public synchronized Thread getCancelThread()
{
return cancelThread;
}
public synchronized void setRollbackTried()
{
rollbackTried = true;
}
public synchronized boolean getRollbackTried()
{
return rollbackTried;
}
public synchronized void clearRunning()
{
running = false;
}
public synchronized boolean getRunning()
{
return running;
}
}
}