/** * @param reaperElement the reaper element to reorder in the sorted set. * @param delayMillis the amount of time to increment the element's timeout by. * @return the new soonest timeout in the set (not necessarily that of the reordered element) */ public synchronized long reorder(ReaperElement reaperElement, long delayMillis) { // assume it must be in the sorted list, as it was likely obtained via getFirst... removeSorted(reaperElement); // we could add delay to the original timeout, but using current time is probably safer. reaperElement.setAbsoluteTimeout((System.currentTimeMillis() + delayMillis)); // reinsert into its new position. insertSorted(reaperElement); // getFirst takes care of flushing the pending set for us. return getFirst().getAbsoluteTimeout(); }
public String toString () { return "ReaperElement < "+_control+", "+_timeout+", "+statusName()+", "+_worker+" >"; }
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ReaperElement that = (ReaperElement) o; // could be made more efficient, but this is easier to maintain consistently with compareTo. // note that the comparison includes _absoluteTimeoutMills which is mutable, so weird things // may happen if trying to locate the obj in a collection whilst concurrently mutating it. // fortunately such comparisons are generally done with the obj identity shortcut anyhow. return (compareTo(that) == 0); }
return; ReaperElement reaperElement = new ReaperElement(control, timeout); _lifetime.addAndGet(timeout); 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());
final long next = nextDynamicCheckTime.get(); reaperElement = _reaperElements.getFirst(); nextDynamicCheckTime.set(Long.MAX_VALUE); return; } else { final long nextTimeout = reaperElement.getAbsoluteTimeout(); if(nextTimeout > now) { nextDynamicCheckTime.set(nextTimeout); return; // nothing to do yet. tsLogger.i18NLogger.warn_coordinator_TransactionReaper_18(reaperElement._control.get_uid(), reaperElement.statusName()); reinsertElement(reaperElement, _cancelWaitPeriod); reinsertElement(reaperElement, _cancelWaitPeriod); sb.append("\n"); tsLogger.i18NLogger.wedged_reaperelement(sb.toString()); reinsertElement(reaperElement, _cancelFailWaitPeriod); tsLogger.i18NLogger.error_coordinator_TransactionReaper_5(Integer.toString(_zombieCount));
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) { this.notifyAll(); // TODO: use different lock for shutdown? } } } }
/** * 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) { // arg is an Object because ArjunaTransactionImple.propagationContext does not have a Reapable 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; }
public final long checkingPeriod() { if (_dynamic) { return nextDynamicCheckTime.get() - System.currentTimeMillis(); } else { // if we have a cancel in progress which needs // checking up on then we have to wake up in time // for it whether we are using a static or // dynamic model final ReaperElement head = _reaperElements.getFirst(); if(head != null) { if (head._status != ReaperElement.RUN) { long waitTime = head.getAbsoluteTimeout() - System.currentTimeMillis(); if (waitTime < _checkPeriod) { return waitTime; } } } return _checkPeriod; } }
final long next = nextDynamicCheckTime.get(); reaperElement = _reaperElements.getFirst(); nextDynamicCheckTime.set(Long.MAX_VALUE); return; new Object[] {reaperElement._control.get_uid(), reaperElement.statusName()}); reinsertElement(reaperElement, _cancelWaitPeriod); reinsertElement(reaperElement, _cancelWaitPeriod); reinsertElement(reaperElement, _cancelFailWaitPeriod);
public synchronized void setAllTimeoutsToZero() { flushPending(); for(ReaperElement reaperElement : elementsOrderedByTimeout) { reaperElement.setAbsoluteTimeout(0); } }
public ReaperElement(Reapable control, int timeout) { if (tsLogger.logger.isTraceEnabled()) { tsLogger.logger.trace("ReaperElement::ReaperElement ( " + control + ", " + timeout + " )"); } _control = control; _timeout = timeout; _status = RUN; _worker = null; /* * Given a timeout period in seconds, calculate its absolute value from * the current time of day in milliseconds. */ _absoluteTimeoutMills = (timeout * 1000L) + System.currentTimeMillis(); // add additional variation to distinguish instances created in the same millisecond. _bias = getBiasCounter(); }
return; ReaperElement reaperElement = new ReaperElement(control, timeout); _lifetime.addAndGet(timeout); 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());
final long next = nextDynamicCheckTime.get(); reaperElement = _reaperElements.getFirst(); nextDynamicCheckTime.set(Long.MAX_VALUE); return; } else { final long nextTimeout = reaperElement.getAbsoluteTimeout(); if(nextTimeout > now) { nextDynamicCheckTime.set(nextTimeout); return; // nothing to do yet. tsLogger.i18NLogger.warn_coordinator_TransactionReaper_18(reaperElement._control.get_uid(), reaperElement.statusName()); reinsertElement(reaperElement, _cancelWaitPeriod); reinsertElement(reaperElement, _cancelWaitPeriod); sb.append("\n"); tsLogger.i18NLogger.wedged_reaperelement(sb.toString()); reinsertElement(reaperElement, _cancelFailWaitPeriod); tsLogger.i18NLogger.error_coordinator_TransactionReaper_5(Integer.toString(_zombieCount));
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) { this.notifyAll(); // TODO: use different lock for shutdown? } } } }
/** * 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) { // arg is an Object because ArjunaTransactionImple.propagationContext does not have a Reapable 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; }
public final long checkingPeriod() { if (_dynamic) { return nextDynamicCheckTime.get() - System.currentTimeMillis(); } else { // if we have a cancel in progress which needs // checking up on then we have to wake up in time // for it whether we are using a static or // dynamic model final ReaperElement head = _reaperElements.getFirst(); if(head != null) { if (head._status != ReaperElement.RUN) { long waitTime = head.getAbsoluteTimeout() - System.currentTimeMillis(); if (waitTime < _checkPeriod) { return waitTime; } } } return _checkPeriod; } }
public synchronized void setAllTimeoutsToZero() { flushPending(); for(ReaperElement reaperElement : elementsOrderedByTimeout) { reaperElement.setAbsoluteTimeout(0); } }
public ReaperElement(Reapable control, int timeout) { if (tsLogger.logger.isTraceEnabled()) { tsLogger.logger.trace("ReaperElement::ReaperElement ( " + control + ", " + timeout + " )"); } _control = control; _timeout = timeout; _status = RUN; _worker = null; /* * Given a timeout period in seconds, calculate its absolute value from * the current time of day in milliseconds. */ _absoluteTimeoutMills = (timeout * 1000L) + System.currentTimeMillis(); // add additional variation to distinguish instances created in the same millisecond. _bias = getBiasCounter(); }
return; ReaperElement reaperElement = new ReaperElement(control, timeout); _lifetime.addAndGet(timeout); 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());
final long next = nextDynamicCheckTime.get(); reaperElement = _reaperElements.getFirst(); nextDynamicCheckTime.set(Long.MAX_VALUE); return; } else { final long nextTimeout = reaperElement.getAbsoluteTimeout(); if(nextTimeout > now) { nextDynamicCheckTime.set(nextTimeout); return; // nothing to do yet. tsLogger.i18NLogger.warn_coordinator_TransactionReaper_18(reaperElement._control.get_uid(), reaperElement.statusName()); reinsertElement(reaperElement, _cancelWaitPeriod); reinsertElement(reaperElement, _cancelWaitPeriod); sb.append("\n"); tsLogger.i18NLogger.wedged_reaperelement(sb.toString()); reinsertElement(reaperElement, _cancelFailWaitPeriod); tsLogger.i18NLogger.error_coordinator_TransactionReaper_5(Integer.toString(_zombieCount));