Search in sources :

Example 1 with ReaperElement

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();
            }
        }
    }
}
Also used : ReaperElement(com.arjuna.ats.internal.arjuna.coordinator.ReaperElement)

Example 2 with ReaperElement

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;
}
Also used : ReaperElement(com.arjuna.ats.internal.arjuna.coordinator.ReaperElement)

Example 3 with ReaperElement

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;
}
Also used : ReaperElement(com.arjuna.ats.internal.arjuna.coordinator.ReaperElement)

Example 4 with ReaperElement

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);
    }
}
Also used : ReaperWorkerThread(com.arjuna.ats.internal.arjuna.coordinator.ReaperWorkerThread) ReaperElement(com.arjuna.ats.internal.arjuna.coordinator.ReaperElement)

Example 5 with ReaperElement

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());
    }
}
Also used : ReaperElement(com.arjuna.ats.internal.arjuna.coordinator.ReaperElement)

Aggregations

ReaperElement (com.arjuna.ats.internal.arjuna.coordinator.ReaperElement)7 ReaperWorkerThread (com.arjuna.ats.internal.arjuna.coordinator.ReaperWorkerThread)2 Uid (com.arjuna.ats.arjuna.common.Uid)1 Reapable (com.arjuna.ats.arjuna.coordinator.Reapable)1 TransactionReaper (com.arjuna.ats.arjuna.coordinator.TransactionReaper)1 SortedSet (java.util.SortedSet)1 TreeSet (java.util.TreeSet)1 Test (org.junit.Test)1