final long timeWindow) throws JobPersistenceException {
List<TriggerWrapper> wrappers = new ArrayList<TriggerWrapper>();
Set<JobKey> acquiredJobKeysForNoConcurrentExec = new HashSet<JobKey>();
Set<TriggerWrapper> excludedTriggers = new HashSet<TriggerWrapper>();
JobPersistenceException caughtJpe = null;
long firstAcquiredTriggerFireTime = 0;
try {
while (true) {
TriggerWrapper tw = null;
try {
TriggerKey triggerKey = source.removeFirst();
if (triggerKey != null) {
tw = triggerFacade.get(triggerKey);
}
if (tw == null) break;
} catch (java.util.NoSuchElementException nsee) {
break;
}
if (tw.getNextFireTime() == null) {
continue;
}
// it's possible that we've selected triggers way outside of the max fire ahead time for batches
// (up to idleWaitTime + fireAheadTime) so we need to make sure not to include such triggers.
// So we select from the first next trigger to fire up until the max fire ahead time after that...
// which will perfectly honor the fireAheadTime window because the no firing will occur until
// the first acquired trigger's fire time arrives.
if (firstAcquiredTriggerFireTime > 0
&& tw.getNextFireTime().getTime() > (firstAcquiredTriggerFireTime + timeWindow)) {
source.add(tw);
break;
}
if (applyMisfire(tw)) {
if (tw.getNextFireTime() != null) {
source.add(tw);
}
continue;
}
if (tw.getNextFireTime().getTime() > noLaterThan + timeWindow) {
source.add(tw);
break;
}
if (tw.jobDisallowsConcurrence()) {
if (acquiredJobKeysForNoConcurrentExec.contains(tw.getJobKey())) {
excludedTriggers.add(tw);
continue;
}
acquiredJobKeysForNoConcurrentExec.add(tw.getJobKey());
}
wrappers.add(tw);
if (firstAcquiredTriggerFireTime == 0) firstAcquiredTriggerFireTime = tw.getNextFireTime().getTime();
if (wrappers.size() == maxCount) {
break;
}
}
} catch (JobPersistenceException jpe) {
caughtJpe = jpe; // hold the exception while we patch back up the collection ...
}
// If we did excluded triggers to prevent ACQUIRE state due to DisallowConcurrentExecution, we need to add them back
// to store.
if (excludedTriggers.size() > 0) {
for (TriggerWrapper tw : excludedTriggers) {
source.add(tw);
}
}
// if we held and exception, now we need to put back all the TriggerWrappers that we may have removed from the
// source set
if (caughtJpe != null) {
for (TriggerWrapper tw : wrappers) {
source.add(tw);
}
// and now throw the exception...
throw new JobPersistenceException("Exception encountered while trying to select triggers for firing.", caughtJpe);
}
return wrappers;
}