Search in sources :

Example 1 with TimerImpl

use of org.jboss.as.ejb3.timerservice.TimerImpl in project wildfly by wildfly.

the class TimerServiceImpl method restoreTimers.

/**
     * Restores persisted timers, corresponding to this timerservice, which are eligible for any new timeouts.
     * <p>
     * This includes timers whose {@link TimerState} is <b>neither</b> of the following:
     * <ul>
     * <li>{@link TimerState#CANCELED}</li>
     * <li>{@link TimerState#EXPIRED}</li>
     * </ul>
     * </p>
     * <p>
     * All such restored timers will be schedule for their next timeouts.
     * </p>
     *
     * @param autoTimers
     */
public void restoreTimers(final List<ScheduleTimer> autoTimers) {
    // get the persisted timers which are considered active
    List<TimerImpl> restorableTimers = this.getActivePersistentTimers();
    //timers are removed from the list as they are loaded
    final List<ScheduleTimer> newAutoTimers = new LinkedList<ScheduleTimer>(autoTimers);
    if (EJB3_TIMER_LOGGER.isDebugEnabled()) {
        EJB3_TIMER_LOGGER.debug("Found " + restorableTimers.size() + " active persistentTimers for timedObjectId: " + getInvoker().getTimedObjectId());
    }
    // and scheduling the timer task
    for (final TimerImpl activeTimer : restorableTimers) {
        if (activeTimer.isAutoTimer()) {
            CalendarTimer calendarTimer = (CalendarTimer) activeTimer;
            boolean found = false;
            //so we know we have an auto timer. We need to try and match it up with the auto timers.
            ListIterator<ScheduleTimer> it = newAutoTimers.listIterator();
            while (it.hasNext()) {
                ScheduleTimer timer = it.next();
                final String methodName = timer.getMethod().getName();
                final String[] params = new String[timer.getMethod().getParameterTypes().length];
                for (int i = 0; i < timer.getMethod().getParameterTypes().length; ++i) {
                    params[i] = timer.getMethod().getParameterTypes()[i].getName();
                }
                if (doesTimeoutMethodMatch(calendarTimer.getTimeoutMethod(), methodName, params)) {
                    // and the timer does not change the persistence
                    if (this.doesScheduleMatch(calendarTimer.getScheduleExpression(), timer.getScheduleExpression()) && timer.getTimerConfig().isPersistent()) {
                        it.remove();
                        found = true;
                        break;
                    }
                }
            }
            if (!found) {
                activeTimer.setTimerState(TimerState.CANCELED);
            } else {
                // ensure state switch to active if was TIMEOUT in the DB
                // if the persistence is shared it must be ensured to not update
                // timers of other nodes in the cluster
                activeTimer.setTimerState(TimerState.ACTIVE);
            }
            this.persistTimer(activeTimer, false);
            if (found) {
                startTimer(activeTimer);
                EJB3_TIMER_LOGGER.debugv("Started timer: {0}", activeTimer);
            }
        } else if (!ineligibleTimerStates.contains(activeTimer.getState())) {
            startTimer(activeTimer);
        }
        EJB3_TIMER_LOGGER.debugv("Started timer: {0}", activeTimer);
    }
    for (ScheduleTimer timer : newAutoTimers) {
        this.loadAutoTimer(timer.getScheduleExpression(), timer.getTimerConfig(), timer.getMethod());
    }
}
Also used : LinkedList(java.util.LinkedList) ScheduleTimer(org.jboss.as.ejb3.timerservice.spi.ScheduleTimer) ControlPoint(org.wildfly.extension.requestcontroller.ControlPoint)

Example 2 with TimerImpl

use of org.jboss.as.ejb3.timerservice.TimerImpl in project wildfly by wildfly.

the class DatabaseTimerPersistence method loadActiveTimers.

@Override
public List<TimerImpl> loadActiveTimers(final String timedObjectId, final TimerServiceImpl timerService) {
    if (!knownTimerIds.containsKey(timedObjectId)) {
        // if the timedObjectId has not being deployed
        EjbLogger.EJB3_TIMER_LOGGER.timerNotDeployed(timedObjectId);
        return Collections.emptyList();
    }
    String loadTimer = sql.getProperty(LOAD_ALL_TIMERS);
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    try {
        connection = dataSource.getConnection();
        statement = connection.prepareStatement(loadTimer);
        statement.setString(1, timedObjectId);
        statement.setString(2, partition);
        resultSet = statement.executeQuery();
        final List<Holder> timers = new ArrayList<>();
        while (resultSet.next()) {
            String timerId = null;
            try {
                timerId = resultSet.getString(1);
                final Holder timerImpl = timerFromResult(resultSet, timerService, timerId, null);
                if (timerImpl != null) {
                    timers.add(timerImpl);
                } else {
                    final String deleteTimer = sql.getProperty(DELETE_TIMER);
                    try (PreparedStatement deleteStatement = connection.prepareStatement(deleteTimer)) {
                        deleteStatement.setString(1, resultSet.getString(2));
                        deleteStatement.setString(2, timerId);
                        deleteStatement.setString(3, partition);
                        deleteStatement.execute();
                    }
                }
            } catch (Exception e) {
                EjbLogger.EJB3_TIMER_LOGGER.timerReinstatementFailed(resultSet.getString(2), timerId, e);
            }
        }
        synchronized (this) {
            // ids should be always be not null
            Set<String> ids = knownTimerIds.get(timedObjectId);
            for (Holder timer : timers) {
                ids.add(timer.timer.getId());
            }
            for (Holder timer : timers) {
                if (timer.requiresReset) {
                    TimerImpl ret = timer.timer;
                    EjbLogger.DEPLOYMENT_LOGGER.loadedPersistentTimerInTimeout(ret.getId(), ret.getTimedObjectId());
                    if (ret.getNextExpiration() == null) {
                        ret.setTimerState(TimerState.CANCELED, null);
                        persistTimer(ret);
                    } else {
                        ret.setTimerState(TimerState.ACTIVE, null);
                        persistTimer(ret);
                    }
                }
            }
        }
        List<TimerImpl> ret = new ArrayList<>();
        for (Holder timer : timers) {
            ret.add(timer.timer);
        }
        return ret;
    } catch (SQLException e) {
        throw new RuntimeException(e);
    } finally {
        safeClose(resultSet);
        safeClose(statement);
        safeClose(connection);
    }
}
Also used : SQLException(java.sql.SQLException) Connection(java.sql.Connection) ArrayList(java.util.ArrayList) PreparedStatement(java.sql.PreparedStatement) ParseException(java.text.ParseException) HeuristicRollbackException(javax.transaction.HeuristicRollbackException) HeuristicMixedException(javax.transaction.HeuristicMixedException) SQLException(java.sql.SQLException) RollbackException(javax.transaction.RollbackException) StartException(org.jboss.msc.service.StartException) IOException(java.io.IOException) NotSupportedException(javax.transaction.NotSupportedException) SystemException(javax.transaction.SystemException) ResultSet(java.sql.ResultSet) TimerImpl(org.jboss.as.ejb3.timerservice.TimerImpl)

Example 3 with TimerImpl

use of org.jboss.as.ejb3.timerservice.TimerImpl in project wildfly by wildfly.

the class LegacyFileStore method loadTimersFromFile.

static Map<String, TimerImpl> loadTimersFromFile(final String timedObjectId, final TimerServiceImpl timerService, String directory, MarshallerFactory factory, MarshallingConfiguration configuration) {
    final Map<String, TimerImpl> timers = new HashMap<String, TimerImpl>();
    Unmarshaller unmarshaller = null;
    try {
        final File file = new File(directory);
        if (!file.exists()) {
            // no timers exist yet
            return timers;
        } else if (!file.isDirectory()) {
            EJB3_TIMER_LOGGER.failToRestoreTimers(file);
            return timers;
        }
        File marker = new File(file, MIGRATION_MARKER);
        if (marker.exists()) {
            return timers;
        }
        unmarshaller = factory.createUnmarshaller(configuration);
        for (File timerFile : file.listFiles()) {
            if (timerFile.getName().endsWith(".xml")) {
                continue;
            }
            FileInputStream in = null;
            try {
                in = new FileInputStream(timerFile);
                unmarshaller.start(new InputStreamByteInput(in));
                final TimerEntity entity = unmarshaller.readObject(TimerEntity.class);
                // we load the legacy timer entity class, and turn it into a timer state
                TimerImpl.Builder builder;
                if (entity instanceof CalendarTimerEntity) {
                    CalendarTimerEntity c = (CalendarTimerEntity) entity;
                    final ScheduleExpression scheduleExpression = new ScheduleExpression();
                    scheduleExpression.second(c.getSecond()).minute(c.getMinute()).hour(c.getHour()).dayOfWeek(c.getDayOfWeek()).dayOfMonth(c.getDayOfMonth()).month(c.getMonth()).year(c.getYear()).start(c.getStartDate()).end(c.getEndDate()).timezone(c.getTimezone());
                    builder = CalendarTimer.builder().setScheduleExpression(scheduleExpression).setAutoTimer(c.isAutoTimer()).setTimeoutMethod(CalendarTimer.getTimeoutMethod(c.getTimeoutMethod(), timerService.getTimedObjectInvoker().getValue().getClassLoader()));
                } else {
                    builder = TimerImpl.builder();
                }
                builder.setId(entity.getId()).setTimedObjectId(entity.getTimedObjectId()).setInitialDate(entity.getInitialDate()).setRepeatInterval(entity.getInterval()).setNextDate(entity.getNextDate()).setPreviousRun(entity.getPreviousRun()).setInfo(entity.getInfo()).setTimerState(entity.getTimerState()).setPersistent(true);
                timers.put(entity.getId(), builder.build(timerService));
                unmarshaller.finish();
            } catch (Exception e) {
                EJB3_TIMER_LOGGER.failToRestoreTimersFromFile(timerFile, e);
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        EJB3_TIMER_LOGGER.failToCloseFile(e);
                    }
                }
            }
        }
        if (!timers.isEmpty()) {
            Files.write(marker.toPath(), new Date().toString().getBytes(StandardCharsets.UTF_8));
        }
    } catch (Exception e) {
        EJB3_TIMER_LOGGER.failToRestoreTimersForObjectId(timedObjectId, e);
    } finally {
        VFSUtils.safeClose(unmarshaller);
    }
    return timers;
}
Also used : ScheduleExpression(javax.ejb.ScheduleExpression) HashMap(java.util.HashMap) CalendarTimerEntity(org.jboss.as.ejb3.timerservice.persistence.CalendarTimerEntity) TimerEntity(org.jboss.as.ejb3.timerservice.persistence.TimerEntity) CalendarTimerEntity(org.jboss.as.ejb3.timerservice.persistence.CalendarTimerEntity) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) IOException(java.io.IOException) Date(java.util.Date) InputStreamByteInput(org.jboss.marshalling.InputStreamByteInput) TimerImpl(org.jboss.as.ejb3.timerservice.TimerImpl) Unmarshaller(org.jboss.marshalling.Unmarshaller) File(java.io.File)

Example 4 with TimerImpl

use of org.jboss.as.ejb3.timerservice.TimerImpl in project wildfly by wildfly.

the class FileTimerPersistence method persistTimer.

private void persistTimer(final TimerImpl timer, boolean newTimer) {
    final Lock lock = getLock(timer.getTimedObjectId());
    try {
        final int status = ContextTransactionManager.getInstance().getStatus();
        if (status == Status.STATUS_MARKED_ROLLBACK || status == Status.STATUS_ROLLEDBACK || status == Status.STATUS_ROLLING_BACK) {
            // no need to persist anyway
            return;
        }
        lock.lock();
        if (status == Status.STATUS_NO_TRANSACTION || status == Status.STATUS_UNKNOWN || isBeforeCompletion() || status == Status.STATUS_COMMITTED) {
            Map<String, TimerImpl> map = getTimers(timer.getTimedObjectId(), timer.getTimerService());
            if (timer.getState() == TimerState.CANCELED || timer.getState() == TimerState.EXPIRED) {
                map.remove(timer.getId());
                writeFile(timer);
            } else if (newTimer || map.containsKey(timer.getId())) {
                // if it is not a new timer and is not in the map then it has
                // been removed by another thread.
                map.put(timer.getId(), timer);
                writeFile(timer);
            }
        } else {
            final String key = timerTransactionKey(timer);
            Object existing = transactionSynchronizationRegistry.getValue().getResource(key);
            // check is there is already a persist sync for this timer
            if (existing == null) {
                transactionSynchronizationRegistry.getValue().registerInterposedSynchronization(new PersistTransactionSynchronization(lock, key, newTimer));
            }
            // update the most recent version of the timer to be persisted
            transactionSynchronizationRegistry.getValue().putResource(key, timer);
        }
    } catch (SystemException e) {
        throw new RuntimeException(e);
    } finally {
        lock.unlock();
    }
}
Also used : SystemException(javax.transaction.SystemException) TimerImpl(org.jboss.as.ejb3.timerservice.TimerImpl) ReentrantLock(java.util.concurrent.locks.ReentrantLock) Lock(java.util.concurrent.locks.Lock)

Example 5 with TimerImpl

use of org.jboss.as.ejb3.timerservice.TimerImpl in project wildfly by wildfly.

the class FileTimerPersistence method mostRecentEntityVersion.

/**
 * Returns either the loaded entity or the most recent version of the entity that has
 * been persisted in this transaction.
 */
private TimerImpl mostRecentEntityVersion(final TimerImpl timerImpl) {
    try {
        final int status = ContextTransactionManager.getInstance().getStatus();
        if (status == Status.STATUS_UNKNOWN || status == Status.STATUS_NO_TRANSACTION) {
            return timerImpl;
        }
        final String key = timerTransactionKey(timerImpl);
        TimerImpl existing = (TimerImpl) transactionSynchronizationRegistry.getValue().getResource(key);
        return existing != null ? existing : timerImpl;
    } catch (SystemException e) {
        throw new RuntimeException(e);
    }
}
Also used : SystemException(javax.transaction.SystemException) TimerImpl(org.jboss.as.ejb3.timerservice.TimerImpl)

Aggregations

TimerImpl (org.jboss.as.ejb3.timerservice.TimerImpl)11 CalendarTimer (org.jboss.as.ejb3.timerservice.CalendarTimer)5 IOException (java.io.IOException)4 SystemException (javax.transaction.SystemException)4 Method (java.lang.reflect.Method)3 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 ScheduleExpression (javax.ejb.ScheduleExpression)3 TimeoutMethod (org.jboss.as.ejb3.timerservice.persistence.TimeoutMethod)3 File (java.io.File)2 FileInputStream (java.io.FileInputStream)2 Serializable (java.io.Serializable)2 Connection (java.sql.Connection)2 PreparedStatement (java.sql.PreparedStatement)2 ResultSet (java.sql.ResultSet)2 SQLException (java.sql.SQLException)2 Date (java.util.Date)2 Map (java.util.Map)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 ConcurrentMap (java.util.concurrent.ConcurrentMap)2