Search in sources :

Example 6 with TimerPrimaryKey

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;
}
Also used : TimerPrimaryKey(com.sun.ejb.containers.TimerPrimaryKey) HashMap(java.util.HashMap) EJBTimerSchedule(com.sun.ejb.containers.EJBTimerSchedule) Method(java.lang.reflect.Method) PropertyVetoException(java.beans.PropertyVetoException) EJBException(javax.ejb.EJBException) FinderException(javax.ejb.FinderException) CreateException(javax.ejb.CreateException) TransactionManager(javax.transaction.TransactionManager) List(java.util.List) ArrayList(java.util.ArrayList) RuntimeTimerState(com.sun.ejb.containers.RuntimeTimerState) Map(java.util.Map) HashMap(java.util.HashMap)

Example 7 with TimerPrimaryKey

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;
}
Also used : TimerPrimaryKey(com.sun.ejb.containers.TimerPrimaryKey) RuntimeTimerState(com.sun.ejb.containers.RuntimeTimerState) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) EJBTimerSchedule(com.sun.ejb.containers.EJBTimerSchedule) Date(java.util.Date) BaseContainer(com.sun.ejb.containers.BaseContainer) Iterator(java.util.Iterator) RuntimeTimerState(com.sun.ejb.containers.RuntimeTimerState) Map(java.util.Map) HashMap(java.util.HashMap) HashSet(java.util.HashSet)

Example 8 with TimerPrimaryKey

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);
    }
}
Also used : TimerPrimaryKey(com.sun.ejb.containers.TimerPrimaryKey) TransactionManager(javax.transaction.TransactionManager) Collection(java.util.Collection) FinderException(javax.ejb.FinderException) EJBException(javax.ejb.EJBException)

Example 9 with TimerPrimaryKey

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;
}
Also used : TimerPrimaryKey(com.sun.ejb.containers.TimerPrimaryKey) HashMap(java.util.HashMap) EJBTimerSchedule(com.sun.ejb.containers.EJBTimerSchedule) ScheduledTimerDescriptor(org.glassfish.ejb.deployment.descriptor.ScheduledTimerDescriptor) Method(java.lang.reflect.Method) FinderException(javax.ejb.FinderException) EJBException(javax.ejb.EJBException) Collection(java.util.Collection) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) IMap(com.hazelcast.core.IMap) HashSet(java.util.HashSet)

Example 10 with TimerPrimaryKey

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);
    }
}
Also used : TimerPrimaryKey(com.sun.ejb.containers.TimerPrimaryKey) TransactionManager(javax.transaction.TransactionManager) HashSet(java.util.HashSet)

Aggregations

TimerPrimaryKey (com.sun.ejb.containers.TimerPrimaryKey)10 HashSet (java.util.HashSet)8 EJBTimerSchedule (com.sun.ejb.containers.EJBTimerSchedule)5 RuntimeTimerState (com.sun.ejb.containers.RuntimeTimerState)5 HashMap (java.util.HashMap)5 Map (java.util.Map)5 IMap (com.hazelcast.core.IMap)3 BaseContainer (com.sun.ejb.containers.BaseContainer)3 Collection (java.util.Collection)3 Date (java.util.Date)3 Iterator (java.util.Iterator)3 EJBException (javax.ejb.EJBException)3 FinderException (javax.ejb.FinderException)3 TransactionManager (javax.transaction.TransactionManager)3 Method (java.lang.reflect.Method)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 Set (java.util.Set)2 PropertyVetoException (java.beans.PropertyVetoException)1 CreateException (javax.ejb.CreateException)1