use of com.sun.ejb.containers.TimerPrimaryKey in project Payara by payara.
the class PersistentEJBTimerService method recoverAndCreateSchedules.
/**
* Recover pre-existing timers associated with the Container identified
* by the containerId, and create automatic timers defined by the @Schedule
* annotation on the EJB bean.
*
* If it is called from deploy on a non-clustered instance, both
* persistent and non-persistent timers will be created.
* Otherwise only non-persistent timers are created by this method.
*
* @return a Map of both, restored and created timers, where the key is TimerPrimaryKey
* and the value is the Method to be executed by the container when the timer with
* this PK times out.
*/
@Override
protected Map<TimerPrimaryKey, Method> recoverAndCreateSchedules(long containerId, long applicationId, Map<Method, List<ScheduledTimerDescriptor>> schedules, boolean deploy) {
Map<TimerPrimaryKey, Method> result = new HashMap<TimerPrimaryKey, Method>();
TransactionManager tm = ejbContainerUtil.getTransactionManager();
try {
tm.begin();
Set<TimerState> timers = _restoreTimers((Set<TimerState>) timerLocal_.findActiveTimersOwnedByThisServerByContainer(containerId));
if (timers.size() > 0) {
logger.log(Level.FINE, "Found " + timers.size() + " persistent timers for containerId: " + containerId);
}
boolean schedulesExist = (schedules.size() > 0);
for (TimerState timer : timers) {
EJBTimerSchedule ts = timer.getTimerSchedule();
if (ts != null && ts.isAutomatic() && schedulesExist) {
for (Map.Entry<Method, List<ScheduledTimerDescriptor>> entry : schedules.entrySet()) {
Method m = entry.getKey();
if (m.getName().equals(ts.getTimerMethodName()) && m.getParameterTypes().length == ts.getMethodParamCount()) {
result.put(new TimerPrimaryKey(timer.getTimerId()), m);
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "@@@ FOUND existing schedule: " + ts.getScheduleAsString() + " FOR method: " + m);
}
}
}
}
}
createSchedules(containerId, applicationId, schedules, result, ownerIdOfThisServer_, true, (deploy && isDas));
tm.commit();
} catch (Exception e) {
recoverAndCreateSchedulesError(e, tm);
}
return result;
}
use of com.sun.ejb.containers.TimerPrimaryKey in project Payara by payara.
the class PersistentEJBTimerService method _restoreTimers.
/**
* The portion of timer restoration that deals with registering the
* JDK timer tasks and checking for missed expirations.
* @return the Set of restored timers
*/
private Set<TimerState> _restoreTimers(Set<TimerState> timersEligibleForRestoration) {
// Do timer restoration in two passes. The first pass updates
// the timer cache with each timer. The second pass schedules
// the JDK timer tasks.
Map timersToRestore = new HashMap();
Set timerIdsToRemove = new HashSet();
Set<TimerState> result = new HashSet<TimerState>();
for (TimerState timer : timersEligibleForRestoration) {
TimerPrimaryKey timerId = getPrimaryKey(timer);
if (getTimerState(timerId) != null) {
// Already restored. Add it to the result but do nothing else.
logger.log(Level.FINE, "@@@ Timer already restored: " + timer);
result.add(timer);
continue;
}
long containerId = timer.getContainerId();
// Timer might refer to an obsolete container.
BaseContainer container = getContainer(containerId);
if (container != null) {
// Update applicationId if it is null (from previous version)
long appid = timer.getApplicationId();
if (appid == 0) {
timer.setApplicationId(container.getApplicationId());
}
// End update
Date initialExpiration = timer.getInitialExpiration();
// Create an instance of RuntimeTimerState.
// Only access timedObjectPrimaryKey if timed object is
// an entity bean. That allows us to lazily load the underlying
// blob for stateless session and message-driven bean timers.
Object timedObjectPrimaryKey = null;
if (container.getContainerType() == BaseContainer.ContainerType.ENTITY) {
timedObjectPrimaryKey = timer.getTimedObjectPrimaryKey();
}
RuntimeTimerState timerState = new RuntimeTimerState(timerId, initialExpiration, timer.getIntervalDuration(), container, timedObjectPrimaryKey, timer.getTimerSchedule(), // Don't need to store the info ref for persistent timer
null, true);
timerCache_.addTimer(timerId, timerState);
// If a single-action timer is still in the database it never
// successfully delivered, so always reschedule a timer task
// for it. For periodic timers, we use the last known
// expiration time to decide whether we need to fire one
// ejbTimeout to make up for any missed ones.
Date expirationTime = initialExpiration;
Date now = new Date();
if (timerState.isPeriodic()) {
// lastExpiration time, or null if we either aren't
// tracking last expiration or an expiration hasn't
// occurred yet for this timer.
Date lastExpiration = timer.getLastExpiration();
EJBTimerSchedule ts = timer.getTimerSchedule();
if ((lastExpiration == null) && now.after(initialExpiration)) {
if (!timerState.isExpired()) {
// This timer didn't even expire one time.
logger.log(Level.INFO, "Rescheduling missed expiration for " + "periodic timer " + timerState + ". Timer expirations should " + " have been delivered starting at " + initialExpiration);
}
// keep expiration time at initialExpiration. That
// will force an ejbTimeout almost immediately. After
// that the timer will return to fixed rate expiration.
} else if ((lastExpiration != null) && ((ts != null && ts.getNextTimeout(lastExpiration).getTimeInMillis() < now.getTime()) || ((ts == null) && now.getTime() - lastExpiration.getTime() > timer.getIntervalDuration()))) {
// Schedule-based timer is periodic
logger.log(Level.INFO, "Rescheduling missed expiration for " + "periodic timer " + timerState + ". Last timer expiration " + "occurred at " + lastExpiration);
// Timer expired at least once and at least one
// missed expiration has occurred.
// keep expiration time at initialExpiration. That
// will force an ejbTimeout almost immediately. After
// that the timer will return to fixed rate expiration.
} else {
// In this case, at least one expiration has occurred
// but that was less than one period ago so there were
// no missed expirations.
expirationTime = calcNextFixedRateExpiration(timerState);
}
} else {
if (now.after(initialExpiration)) {
logger.log(Level.INFO, "Rescheduling missed expiration for " + "single-action timer " + timerState + ". Timer expiration should " + " have been delivered at " + initialExpiration);
}
}
if (expirationTime == null) {
// Schedule-based timer will never expire again - remove it.
logger.log(Level.INFO, "Removing schedule-based timer " + timerState + " that will never expire again");
timerIdsToRemove.add(timerId);
} else {
timersToRestore.put(timerState, expirationTime);
result.add(timer);
}
} else {
// Timed object's container no longer exists - remember its id.
logger.log(Level.FINE, "Skipping timer " + timerId + " for container that is not up: " + containerId);
}
}
if (timerIdsToRemove.size() > 0) {
timerLocal_.remove(timerIdsToRemove);
}
for (Iterator entries = timersToRestore.entrySet().iterator(); entries.hasNext(); ) {
Map.Entry next = (Map.Entry) entries.next();
RuntimeTimerState nextTimer = (RuntimeTimerState) next.getKey();
TimerPrimaryKey timerId = nextTimer.getTimerId();
Date expiration = (Date) next.getValue();
scheduleTask(timerId, expiration);
logger.log(Level.FINE, "EJBTimerService.restoreTimers(), scheduling timer " + nextTimer);
}
logger.log(Level.FINE, "DONE EJBTimerService.restoreTimers()");
return result;
}
use of com.sun.ejb.containers.TimerPrimaryKey in project Payara by payara.
the class HazelcastTimerStore method createSchedules.
@Override
public void createSchedules(long containerId, long applicationId, Map<MethodDescriptor, List<ScheduledTimerDescriptor>> methodDescriptorSchedules, String server_name) {
TransactionManager tm = ejbContainerUtil.getTransactionManager();
try {
tm.begin();
Collection<TimerPrimaryKey> keys = (Collection<TimerPrimaryKey>) containerCache.get(containerId);
if (keys == null || keys.isEmpty()) {
// No timers owned by this EJB
createSchedules(containerId, applicationId, methodDescriptorSchedules, null, server_name, false, true);
}
tm.commit();
} catch (Exception e) {
recoverAndCreateSchedulesError(e, tm);
}
}
use of com.sun.ejb.containers.TimerPrimaryKey in project Payara by payara.
the class HazelcastTimerStore method recoverAndCreateSchedules.
@Override
protected Map<TimerPrimaryKey, Method> recoverAndCreateSchedules(long containerId, long applicationId, Map<Method, List<ScheduledTimerDescriptor>> schedules, boolean deploy) {
Map<TimerPrimaryKey, Method> result = new HashMap<TimerPrimaryKey, Method>();
boolean lostCluster = false;
Set<HZTimer> activeTimers = new HashSet<>();
// get all timers for this container
Collection<TimerPrimaryKey> containerKeys = (Collection<TimerPrimaryKey>) containerCache.get(containerId);
Collection<TimerPrimaryKey> deadKeys = new HashSet<>();
if (containerKeys != null) {
for (TimerPrimaryKey containerKey : containerKeys) {
HZTimer timer = (HZTimer) pkCache.get(containerKey.timerId);
if (timer != null && timer.getMemberName().equals(this.serverName)) {
activeTimers.add(timer);
} else if (timer == null) {
deadKeys.add(containerKey);
}
}
if (!deadKeys.isEmpty()) {
// clean out dead keys
logger.info("Cleaning out " + deadKeys.size() + " dead timer ids from Container Cache ");
for (TimerPrimaryKey deadKey : deadKeys) {
containerKeys.remove(deadKey);
}
containerCache.put(containerId, containerKeys);
}
} else if (containerKeys == null && deploy == false) {
// we are in trouble as we are not deploying but our keys are null
// looks like we lost the whole cluster storage
// recreate timers
logger.log(Level.INFO, "Looks like we lost the data grid storage will recreate timers");
lostCluster = true;
}
Set<HZTimer> timers = _restoreTimers(activeTimers);
if (timers.size() > 0) {
logger.log(Level.FINE, "Found " + timers.size() + " persistent timers for containerId: " + containerId);
}
boolean schedulesExist = (schedules.size() > 0);
for (HZTimer timer : timers) {
EJBTimerSchedule ts = timer.getSchedule();
if (ts != null && ts.isAutomatic() && schedulesExist) {
Iterator<Map.Entry<Method, List<ScheduledTimerDescriptor>>> schedulesIterator = schedules.entrySet().iterator();
while (schedulesIterator.hasNext()) {
Map.Entry<Method, List<ScheduledTimerDescriptor>> entry = schedulesIterator.next();
Method m = entry.getKey();
if (m.getName().equals(ts.getTimerMethodName()) && m.getParameterTypes().length == ts.getMethodParamCount()) {
result.put(new TimerPrimaryKey(timer.getKey().getTimerId()), m);
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "@@@ FOUND existing schedule: " + ts.getScheduleAsString() + " FOR method: " + m);
}
schedulesIterator.remove();
}
}
}
}
try {
if (!schedules.isEmpty()) {
createSchedules(containerId, applicationId, schedules, result, serverName, true, (deploy && isDas) || lostCluster);
}
} catch (Exception ex) {
Logger.getLogger(HazelcastTimerStore.class.getName()).log(Level.SEVERE, null, ex);
}
return result;
}
use of com.sun.ejb.containers.TimerPrimaryKey in project Payara by payara.
the class HazelcastTimerStore method _createTimer.
@Override
protected void _createTimer(TimerPrimaryKey timerId, long containerId, long applicationId, Object timedObjectPrimaryKey, String server_name, Date initialExpiration, long intervalDuration, EJBTimerSchedule schedule, TimerConfig timerConfig) throws Exception {
if (timerConfig.isPersistent()) {
pkCache.put(timerId.timerId, new HZTimer(timerId, containerId, applicationId, timedObjectPrimaryKey, server_name, server_name, initialExpiration, intervalDuration, schedule, timerConfig));
// add to container cache
HashSet<TimerPrimaryKey> keysForContainer = (HashSet<TimerPrimaryKey>) containerCache.get(containerId);
if (keysForContainer == null) {
keysForContainer = new HashSet<>();
}
keysForContainer.add(timerId);
containerCache.put(containerId, keysForContainer);
// add to application cache
HashSet<TimerPrimaryKey> keysForApp = (HashSet<TimerPrimaryKey>) applicationCache.get(applicationId);
if (keysForApp == null) {
keysForApp = new HashSet<>();
}
keysForApp.add(timerId);
applicationCache.put(applicationId, keysForApp);
TransactionManager tm = ejbContainerUtil.getTransactionManager();
boolean localTx = tm.getTransaction() == null;
if (localTx) {
tm.begin();
}
addTimerSynchronization(null, timerId.getTimerId(), initialExpiration, containerId, ownerIdOfThisServer_, true);
if (localTx) {
tm.commit();
}
} else {
addTimerSynchronization(null, timerId.getTimerId(), initialExpiration, containerId, ownerIdOfThisServer_, false);
}
}
Aggregations