/// <summary> /// Store the given <see cref="Trigger" />. /// </summary> /// <param name="ctxt">The scheduling context.</param> /// <param name="newTrigger">The <see cref="Trigger" /> to be stored.</param> /// <param name="replaceExisting">If <see langword="true" />, any <see cref="Trigger" /> existing in /// the <see cref="IJobStore" /> with the same name and group should /// be over-written.</param> public virtual void StoreTrigger(SchedulingContext ctxt, Trigger newTrigger, bool replaceExisting) { TriggerWrapper tw = new TriggerWrapper((Trigger)newTrigger.Clone()); if (triggersByFQN[tw.key] != null) { if (!replaceExisting) { throw new ObjectAlreadyExistsException(newTrigger); } // don't delete orphaned job, this trigger has the job anyways RemoveTrigger(ctxt, newTrigger.Name, newTrigger.Group, false); } if (RetrieveJob(ctxt, newTrigger.JobName, newTrigger.JobGroup) == null) { throw new JobPersistenceException("The job (" + newTrigger.FullJobName + ") referenced by the trigger does not exist."); } lock (triggerLock) { // add to triggers array triggers.Add(tw); // add to triggers by group IDictionary grpMap = (Hashtable) triggersByGroup[newTrigger.Group]; if (grpMap == null) { grpMap = new Hashtable(100); triggersByGroup[newTrigger.Group] = grpMap; } grpMap[newTrigger.Name] = tw; // add to triggers by FQN map triggersByFQN[tw.key] = tw; if (pausedTriggerGroups.Contains(newTrigger.Group) || pausedJobGroups.Contains(newTrigger.JobGroup)) { tw.state = InternalTriggerState.Paused; if (blockedJobs.Contains(tw.jobKey)) { tw.state = InternalTriggerState.PausedAndBlocked; } } else if (blockedJobs.Contains(tw.jobKey)) { tw.state = InternalTriggerState.Blocked; } else { timeTriggers.Add(tw); } } }
/// <summary> /// Applies the misfire. /// </summary> /// <param name="tw">The trigger wrapper.</param> /// <returns></returns> protected internal virtual bool ApplyMisfire(TriggerWrapper tw) { DateTime misfireTime = DateTime.UtcNow; if (MisfireThreshold > TimeSpan.Zero) { misfireTime = misfireTime.AddMilliseconds(-1 * MisfireThreshold.TotalMilliseconds); } NullableDateTime tnft = tw.trigger.GetNextFireTimeUtc(); if (!tnft.HasValue || tnft.Value > misfireTime) { return false; } ICalendar cal = null; if (tw.trigger.CalendarName != null) { cal = RetrieveCalendar(null, tw.trigger.CalendarName); } signaler.NotifyTriggerListenersMisfired(tw.trigger); tw.trigger.UpdateAfterMisfire(cal); if (!tw.trigger.GetNextFireTimeUtc().HasValue) { tw.state = InternalTriggerState.Complete; signaler.NotifySchedulerListenersFinalized(tw.trigger); lock (triggerLock) { timeTriggers.Remove(tw); } } else if (tnft.Equals(tw.trigger.GetNextFireTimeUtc())) { return false; } return true; }