use of com.arjuna.ats.internal.arjuna.coordinator.ReaperElement in project narayana by jbosstm.
the class TransactionReaper method removeElementReaper.
/*
* Remove element from list and trigger waiter if we are
* being shutdown.
*
*/
// called internally by the reaper when removing elements - note the different
// behaviour with regard to check time recalculation. Here we need to ensure the
// new time is correct.
private final void removeElementReaper(ReaperElement reaperElement) {
_reaperElements.remove(reaperElement);
_timeouts.remove(reaperElement._control);
synchronized (this) {
// TODO set needs tobe atomic to getFirst?
ReaperElement first = _reaperElements.getFirst();
if (first != null) {
nextDynamicCheckTime.set(first.getAbsoluteTimeout());
} else {
nextDynamicCheckTime.set(Long.MAX_VALUE);
if (_inShutdown) {
// TODO: use different lock for shutdown?
this.notifyAll();
}
}
}
}
use of com.arjuna.ats.internal.arjuna.coordinator.ReaperElement in project narayana by jbosstm.
the class TransactionReaper method getTimeout.
/**
* Given a Control, return the associated timeout, or 0 if we do not know
* about it.
*
* Return in seconds!
*
* Takes an Object because TransactionFactoryImple.getTransactionInfo and
* ArjunaTransactionImple.propagationContext use it and don't have a Reapable.
*/
public final int getTimeout(Object control) {
if ((_timeouts.isEmpty()) || (control == null)) {
if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("TransactionReaper::getTimeout for " + control + " returning 0");
}
return 0;
}
final ReaperElement reaperElement = _timeouts.get(control);
int timeout = (reaperElement == null ? 0 : reaperElement._timeout);
tsLogger.logger.trace("TransactionReaper::getTimeout for " + control + " returning " + timeout);
return timeout;
}
use of com.arjuna.ats.internal.arjuna.coordinator.ReaperElement in project narayana by jbosstm.
the class TransactionReaper method getRemainingTimeoutMills.
/**
* Given the transaction instance, this will return the time left before the
* transaction is automatically rolled back if it has not been terminated.
*
* @param control
* @return the remaining time in milliseconds.
*/
public final long getRemainingTimeoutMills(Object control) {
if ((_timeouts.isEmpty()) || (control == null)) {
if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("TransactionReaper::getRemainingTimeout for " + control + " returning 0");
}
return 0;
}
final ReaperElement reaperElement = _timeouts.get(control);
long timeout = 0;
if (reaperElement == null) {
timeout = 0;
} else {
// units are in milliseconds at this stage.
timeout = reaperElement.getAbsoluteTimeout() - System.currentTimeMillis();
}
if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("TransactionReaper::getRemainingTimeoutMillis for " + control + " returning " + timeout);
}
return timeout;
}
use of com.arjuna.ats.internal.arjuna.coordinator.ReaperElement in project narayana by jbosstm.
the class TransactionReaper method doCancellations.
public final void doCancellations() {
for (; ; ) {
ReaperElement e;
synchronized (_workQueue) {
try {
e = _workQueue.remove(0);
} catch (IndexOutOfBoundsException ioobe) {
break;
}
}
if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("Reaper Worker " + Thread.currentThread() + " attempting to cancel " + e._control.get_uid());
}
boolean cancelled = false;
Exception exception = null;
synchronized (e) {
e._worker = Thread.currentThread();
e._status = ReaperElement.CANCEL;
e.notifyAll();
}
try {
if (e._control.running()) {
if (e._control.cancel() == ActionStatus.ABORTED) {
cancelled = true;
if (TxStats.enabled()) {
// note that we also count timeouts as application rollbacks via
// the stats unpdate in the TwoPhaseCoordinator cancel() method.
TxStats.getInstance().incrementTimeouts();
}
notifyListeners(e._control, true);
}
}
} catch (Exception e1) {
exception = e1;
}
synchronized (e) {
if (e._status == ReaperElement.ZOMBIE) {
// we need to decrement the zombie count and
// force an immediate thread exit. the reaper
// will have removed the entry from the
// transactions list and started another
// worker thread.
ReaperWorkerThread worker = (ReaperWorkerThread) Thread.currentThread();
worker.shutdown();
synchronized (this) {
_zombieCount--;
}
tsLogger.i18NLogger.warn_coordinator_TransactionReaper_13(Thread.currentThread().toString(), e._control.get_uid(), Integer.toString(_zombieCount));
break;
} else if (cancelled && e._status == ReaperElement.CANCEL_INTERRUPTED) {
// ok the call to cancel() returned true but
// we cannot trust it because the reaper sent
// the thread an interrupt
cancelled = false;
e._status = ReaperElement.FAIL;
e.notifyAll();
} else {
e._status = (cancelled ? ReaperElement.COMPLETE : ReaperElement.FAIL);
e.notifyAll();
}
}
if (cancelled) {
tsLogger.i18NLogger.warn_coordinator_TransactionReaper_7(Thread.currentThread().toString(), e._control.get_uid());
} else if (e._control.running()) {
if (exception != null) {
tsLogger.i18NLogger.warn_coordinator_TransactionReaper_9(Thread.currentThread().toString(), e._control.get_uid(), exception);
} else {
tsLogger.i18NLogger.warn_coordinator_TransactionReaper_8(Thread.currentThread().toString(), e._control.get_uid());
}
try {
if (e._control.preventCommit()) {
// log a successful preventCommit()
tsLogger.i18NLogger.warn_coordinator_TransactionReaper_14(Thread.currentThread().toString(), e._control.get_uid());
notifyListeners(e._control, false);
} else {
// log a failed preventCommit()
tsLogger.i18NLogger.warn_coordinator_TransactionReaper_15(Thread.currentThread().toString(), e._control.get_uid());
}
} catch (Exception e1) {
// log an exception under preventCommit()
tsLogger.i18NLogger.warn_coordinator_TransactionReaper_16(Thread.currentThread().toString(), e._control.get_uid(), e1);
}
}
removeElementReaper(e);
}
}
use of com.arjuna.ats.internal.arjuna.coordinator.ReaperElement in project narayana by jbosstm.
the class TransactionReaper method insert.
/**
* timeout is given in seconds, but we work in milliseconds.
*
* Attempting to insert an element that is already present is an error (IllegalStateException)
*/
public final void insert(Reapable control, int timeout) {
if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("TransactionReaper::insert ( " + control + ", " + timeout + " )");
}
/*
* Ignore if the timeout is zero, since this means the transaction
* should never timeout.
*/
if (timeout == 0)
return;
ReaperElement reaperElement = new ReaperElement(control, timeout);
_lifetime.addAndGet(timeout);
// Note: removal works in reverse order i.e. _reaperElements then _timeouts.
if ((_timeouts.putIfAbsent(reaperElement._control, reaperElement) == null)) {
_reaperElements.add(reaperElement);
} else {
throw new IllegalStateException(tsLogger.i18NLogger.get_coordinator_TransactionReaper_1());
}
if (_dynamic && reaperElement.getAbsoluteTimeout() < nextDynamicCheckTime.get()) {
updateCheckTimeForEarlierInsert(reaperElement.getAbsoluteTimeout());
}
}
Aggregations