/// <summary> /// Create a JobRunShell instance with the given settings. /// </summary> /// <param name="jobRunShellFactory">A handle to the <see cref="IJobRunShellFactory" /> that produced /// this <see cref="JobRunShell" />.</param> /// <param name="scheduler">The <see cref="IScheduler" /> instance that should be made /// available within the <see cref="JobExecutionContext" />.</param> /// <param name="schdCtxt">the <see cref="SchedulingContext" /> that should be used by the /// <see cref="JobRunShell" /> when making updates to the <see cref="IJobStore" />.</param> public JobRunShell(IJobRunShellFactory jobRunShellFactory, IScheduler scheduler, SchedulingContext schdCtxt) { this.jobRunShellFactory = jobRunShellFactory; this.scheduler = scheduler; this.schdCtxt = schdCtxt; log = LogManager.GetLogger(GetType()); }
/// <summary> /// Construct a new <see cref="QuartzSchedulerThread" /> for the given /// <see cref="QuartzScheduler" /> as a non-daemon <see cref="Thread" /> /// with normal priority. /// </summary> internal QuartzSchedulerThread(QuartzScheduler qs, QuartzSchedulerResources qsRsrcs, SchedulingContext ctxt) : this(qs, qsRsrcs, ctxt, qsRsrcs.MakeSchedulerThreadDaemon, (int)ThreadPriority.Normal) { }
/// <summary> /// Trigger the identified <see cref="IJob" /> (Execute it /// now) - with a volatile trigger. /// </summary> public virtual void TriggerJobWithVolatileTrigger(SchedulingContext ctxt, string jobName, string groupName, JobDataMap data) { ValidateState(); if (groupName == null) { groupName = SchedulerConstants.DefaultGroup; } Trigger trig = new SimpleTrigger(NewTriggerId(), SchedulerConstants.DefaultManualTriggers, jobName, groupName, DateTime.UtcNow, null, 0, TimeSpan.Zero); trig.Volatile = true; trig.ComputeFirstFireTimeUtc(null); if (data != null) { trig.JobDataMap = data; } bool collision = true; while (collision) { try { resources.JobStore.StoreTrigger(ctxt, trig, false); collision = false; } catch (ObjectAlreadyExistsException) { trig.Name = NewTriggerId(); } } NotifySchedulerThread(trig.GetNextFireTimeUtc()); NotifySchedulerListenersScheduled(trig); }
/// <summary> /// Remove the indicated <see cref="Trigger" /> from the /// scheduler. /// </summary> public virtual bool UnscheduleJob(SchedulingContext ctxt, string triggerName, string groupName) { ValidateState(); if (groupName == null) { groupName = SchedulerConstants.DefaultGroup; } if (resources.JobStore.RemoveTrigger(ctxt, triggerName, groupName)) { NotifySchedulerThread(null); NotifySchedulerListenersUnscheduled(triggerName, groupName); } else { return false; } return true; }
/// <summary> /// Add the given <see cref="IJob" /> to the Scheduler - with no associated /// <see cref="Trigger" />. The <see cref="IJob" /> will be 'dormant' until /// it is scheduled with a <see cref="Trigger" />, or <see cref="IScheduler.TriggerJob(string ,string)" /> /// is called for it. /// <p> /// The <see cref="IJob" /> must by definition be 'durable', if it is not, /// SchedulerException will be thrown. /// </p> /// </summary> public virtual void AddJob(SchedulingContext ctxt, JobDetail jobDetail, bool replace) { ValidateState(); if (!jobDetail.Durable && !replace) { throw new SchedulerException("Jobs added with no trigger must be durable.", SchedulerException.ErrorClientError); } resources.JobStore.StoreJob(ctxt, jobDetail, replace); }
/// <summary> /// Add the <see cref="IJob" /> identified by the given /// <see cref="JobDetail" /> to the Scheduler, and /// associate the given <see cref="Trigger" /> with it. /// <p> /// If the given Trigger does not reference any <see cref="IJob" />, then it /// will be set to reference the Job passed with it into this method. /// </p> /// </summary> public virtual DateTime ScheduleJob(SchedulingContext ctxt, JobDetail jobDetail, Trigger trigger) { ValidateState(); if (jobDetail == null) { throw new SchedulerException("JobDetail cannot be null", SchedulerException.ErrorClientError); } if (trigger == null) { throw new SchedulerException("Trigger cannot be null", SchedulerException.ErrorClientError); } jobDetail.Validate(); if (trigger.JobName == null) { trigger.JobName = jobDetail.Name; trigger.JobGroup = jobDetail.Group; } else if (trigger.JobName != null && !trigger.JobName.Equals(jobDetail.Name)) { throw new SchedulerException("Trigger does not reference given job!", SchedulerException.ErrorClientError); } else if (trigger.JobGroup != null && !trigger.JobGroup.Equals(jobDetail.Group)) { throw new SchedulerException("Trigger does not reference given job!", SchedulerException.ErrorClientError); } trigger.Validate(); ICalendar cal = null; if (trigger.CalendarName != null) { cal = resources.JobStore.RetrieveCalendar(ctxt, trigger.CalendarName); if (cal == null) { throw new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Calendar not found: {0}", trigger.CalendarName), SchedulerException.ErrorPersistenceCalendarDoesNotExist); } } NullableDateTime ft = trigger.ComputeFirstFireTimeUtc(cal); if (!ft.HasValue) { throw new SchedulerException("Based on configured schedule, the given trigger will never fire.", SchedulerException.ErrorClientError); } resources.JobStore.StoreJobAndTrigger(ctxt, jobDetail, trigger); NotifySchedulerThread(trigger.GetNextFireTimeUtc()); NotifySchedulerListenersScheduled(trigger); return ft.Value; }
public bool IsTriggerGroupPaused(SchedulingContext ctxt, string groupName) { return resources.JobStore.IsTriggerGroupPaused(ctxt, groupName); }
/// <summary> /// Notifies the job store job complete. /// </summary> /// <param name="ctxt">The job scheduling context.</param> /// <param name="trigger">The trigger.</param> /// <param name="detail">The detail.</param> /// <param name="instCode">The instruction code.</param> protected internal virtual void NotifyJobStoreJobComplete(SchedulingContext ctxt, Trigger trigger, JobDetail detail, SchedulerInstruction instCode) { resources.JobStore.TriggeredJobComplete(ctxt, trigger, detail, instCode); }
/// <summary> /// Resume (un-pause) all triggers - equivalent of calling <see cref="ResumeTriggerGroup(SchedulingContext, string)" /> /// on every group. /// <p> /// If any <see cref="Trigger" /> missed one or more fire-times, then the /// <see cref="Trigger" />'s misfire instruction will be applied. /// </p> /// </summary> /// <seealso cref="PauseAll(SchedulingContext)" /> public virtual void ResumeAll(SchedulingContext ctxt) { ValidateState(); resources.JobStore.ResumeAll(ctxt); NotifySchedulerThread(null); NotifySchedulerListenersResumedTrigger(null, null); }
/// <summary> /// Resume (un-pause) all of the <see cref="JobDetail" />s /// in the given group. /// <p> /// If any of the <see cref="IJob" /> s had <see cref="Trigger" /> s that /// missed one or more fire-times, then the <see cref="Trigger" />'s /// misfire instruction will be applied. /// </p> /// </summary> public virtual void ResumeJobGroup(SchedulingContext ctxt, string groupName) { ValidateState(); if (groupName == null) { groupName = SchedulerConstants.DefaultGroup; } resources.JobStore.ResumeJobGroup(ctxt, groupName); NotifySchedulerThread(null); NotifySchedulerListenersResumedJob(null, groupName); }
/// <summary> /// Gets the paused trigger groups. /// </summary> /// <param name="ctxt">The the job scheduling context.</param> /// <returns></returns> public virtual ISet GetPausedTriggerGroups(SchedulingContext ctxt) { return resources.JobStore.GetPausedTriggerGroups(ctxt); }
/// <summary> /// Stores the given <see cref="JobDetail" />. /// </summary> /// <param name="ctxt"></param> /// <param name="newJob">The <see cref="JobDetail" /> to be stored.</param> /// <param name="replaceExisting"> /// If <see langword="true" />, any <see cref="IJob" /> existing in the /// <see cref="IJobStore" /> with the same name & group should be over-written. /// </param> public void StoreJob(SchedulingContext ctxt, JobDetail newJob, bool replaceExisting) { ExecuteInLock( (LockOnInsert || replaceExisting) ? LockTriggerAccess : null, new StoreJobCallback(this, ctxt, newJob, replaceExisting)); }
public StoreJobAndTriggerCallback(JobStoreSupport js, JobDetail newJob, Trigger newTrigger, SchedulingContext ctxt) : base(js) { this.newJob = newJob; this.newTrigger = newTrigger; this.ctxt = ctxt; }
/// <summary> /// returns true if the given TriggerGroup /// is paused /// </summary> /// <param name="ctxt"></param> /// <param name="groupName"></param> /// <returns></returns> public bool IsTriggerGroupPaused(SchedulingContext ctxt, string groupName) { throw new NotImplementedException(); }
/// <summary> /// Construct a <see cref="RemoteScheduler" /> instance to proxy the given /// RemoteableQuartzScheduler instance, and with the given /// <see cref="SchedulingContext" />. /// </summary> public RemoteScheduler(SchedulingContext schedCtxt, string schedId) { this.schedCtxt = schedCtxt; this.schedId = schedId; }
/// <summary> /// Store the given <see cref="JobDetail" /> and <see cref="Trigger" />. /// </summary> /// <param name="ctxt">SchedulingContext</param> /// <param name="newJob">Job to be stored.</param> /// <param name="newTrigger">Trigger to be stored.</param> public void StoreJobAndTrigger(SchedulingContext ctxt, JobDetail newJob, Trigger newTrigger) { ExecuteInLock((LockOnInsert) ? LockTriggerAccess : null, new StoreJobAndTriggerCallback(this, newJob, newTrigger, ctxt)); }
/// <summary> /// Get all <see cref="Trigger" /> s that are associated with the /// identified <see cref="JobDetail" />. /// </summary> public virtual Trigger[] GetTriggersOfJob(SchedulingContext ctxt, string jobName, string groupName) { ValidateState(); if (groupName == null) { groupName = SchedulerConstants.DefaultGroup; } return resources.JobStore.GetTriggersForJob(ctxt, jobName, groupName); }
/// <summary> /// Interrupt all instances of the identified InterruptableJob. /// </summary> public virtual bool Interrupt(SchedulingContext ctxt, string jobName, string groupName) { if (groupName == null) { groupName = SchedulerConstants.DefaultGroup; } IList jobs = CurrentlyExecutingJobs; JobDetail jobDetail; bool interrupted = false; foreach (JobExecutionContext jec in jobs) { jobDetail = jec.JobDetail; if (jobName.Equals(jobDetail.Name) && groupName.Equals(jobDetail.Group)) { IJob job = jec.JobInstance; if (job is IInterruptableJob) { ((IInterruptableJob)job).Interrupt(); interrupted = true; } else { throw new UnableToInterruptJobException(string.Format(CultureInfo.InvariantCulture, "Job '{0}' of group '{1}' can not be interrupted, since it does not implement {2}", jobName, groupName, typeof(IInterruptableJob).FullName)); } } } return interrupted; }
/// <summary> /// Get the names of all known <see cref="Trigger" /> /// groups. /// </summary> public virtual string[] GetTriggerGroupNames(SchedulingContext ctxt) { ValidateState(); return resources.JobStore.GetTriggerGroupNames(ctxt); }
/// <summary> /// Create a <see cref="QuartzScheduler" /> with the given configuration /// properties. /// </summary> /// <seealso cref="QuartzSchedulerResources" /> public QuartzScheduler(QuartzSchedulerResources resources, SchedulingContext ctxt, TimeSpan idleWaitTime, TimeSpan dbRetryInterval) { Log = LogManager.GetLogger(GetType()); this.resources = resources; try { Bind(); } catch (Exception re) { throw new SchedulerException("Unable to bind scheduler to remoting context.", re); } schedThread = new QuartzSchedulerThread(this, resources, ctxt); if (idleWaitTime > TimeSpan.Zero) { schedThread.IdleWaitTime = idleWaitTime; } if (dbRetryInterval > TimeSpan.Zero) { schedThread.DbFailureRetryInterval = dbRetryInterval; } jobMgr = new ExecutingJobsManager(); AddGlobalJobListener(jobMgr); errLogger = new ErrorLogger(); AddSchedulerListener(errLogger); signaler = new SchedulerSignalerImpl(this, this.schedThread); Log.Info(string.Format(CultureInfo.InvariantCulture, "Quartz Scheduler v.{0} created.", Version)); }
/// <summary> /// Get the names of all the <see cref="Trigger" />s in /// the given group. /// </summary> public virtual string[] GetTriggerNames(SchedulingContext ctxt, string groupName) { ValidateState(); if (groupName == null) { groupName = SchedulerConstants.DefaultGroup; } return resources.JobStore.GetTriggerNames(ctxt, groupName); }
/// <summary> /// Schedule the given <see cref="Trigger" /> with the /// <see cref="IJob" /> identified by the <see cref="Trigger" />'s settings. /// </summary> public virtual DateTime ScheduleJob(SchedulingContext ctxt, Trigger trigger) { ValidateState(); if (trigger == null) { throw new SchedulerException("Trigger cannot be null", SchedulerException.ErrorClientError); } trigger.Validate(); ICalendar cal = null; if (trigger.CalendarName != null) { cal = resources.JobStore.RetrieveCalendar(ctxt, trigger.CalendarName); if (cal == null) { throw new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Calendar not found: {0}", trigger.CalendarName), SchedulerException.ErrorPersistenceCalendarDoesNotExist); } } NullableDateTime ft = trigger.ComputeFirstFireTimeUtc(cal); if (!ft.HasValue) { throw new SchedulerException("Based on configured schedule, the given trigger will never fire.", SchedulerException.ErrorClientError); } resources.JobStore.StoreTrigger(ctxt, trigger, false); NotifySchedulerThread(trigger.GetNextFireTimeUtc()); NotifySchedulerListenersScheduled(trigger); return ft.Value; }
/// <summary> /// Get the <see cref="JobDetail" /> for the <see cref="IJob" /> /// instance with the given name and group. /// </summary> public virtual JobDetail GetJobDetail(SchedulingContext ctxt, string jobName, string jobGroup) { ValidateState(); if (jobGroup == null) { jobGroup = SchedulerConstants.DefaultGroup; } return resources.JobStore.RetrieveJob(ctxt, jobName, jobGroup); }
/// <summary> /// Delete the identified <see cref="IJob" /> from the Scheduler - and any /// associated <see cref="Trigger" />s. /// </summary> /// <returns> true if the Job was found and deleted.</returns> public virtual bool DeleteJob(SchedulingContext ctxt, string jobName, string groupName) { ValidateState(); if (groupName == null) { groupName = SchedulerConstants.DefaultGroup; } return resources.JobStore.RemoveJob(ctxt, jobName, groupName); }
/// <summary> /// Get the current state of the identified <see cref="Trigger" />. /// </summary> /// <seealso cref="TriggerState.Normal" /> /// <seealso cref="TriggerState.Paused" /> /// <seealso cref="TriggerState.Complete" /> /// <seealso cref="TriggerState.Error" /> public virtual TriggerState GetTriggerState(SchedulingContext ctxt, string triggerName, string triggerGroup) { ValidateState(); if (triggerGroup == null) { triggerGroup = SchedulerConstants.DefaultGroup; } return resources.JobStore.GetTriggerState(ctxt, triggerName, triggerGroup); }
/// <summary> /// Remove (delete) the <see cref="Trigger" /> with the /// given name, and store the new given one - which must be associated /// with the same job. /// </summary> /// <param name="ctxt">The scheduling context.</param> /// <param name="triggerName">The name of the <see cref="Trigger" /> to be removed.</param> /// <param name="groupName">The group name of the <see cref="Trigger" /> to be removed.</param> /// <param name="newTrigger">The new <see cref="Trigger" /> to be stored.</param> /// <returns> /// <see langword="null" /> if a <see cref="Trigger" /> with the given /// name and group was not found and removed from the store, otherwise /// the first fire time of the newly scheduled trigger. /// </returns> public virtual NullableDateTime RescheduleJob(SchedulingContext ctxt, string triggerName, string groupName, Trigger newTrigger) { ValidateState(); if (groupName == null) { groupName = SchedulerConstants.DefaultGroup; } newTrigger.Validate(); ICalendar cal = null; if (newTrigger.CalendarName != null) { cal = resources.JobStore.RetrieveCalendar(ctxt, newTrigger.CalendarName); } NullableDateTime ft = newTrigger.ComputeFirstFireTimeUtc(cal); if (!ft.HasValue) { throw new SchedulerException("Based on configured schedule, the given trigger will never fire.", SchedulerException.ErrorClientError); } if (resources.JobStore.ReplaceTrigger(ctxt, triggerName, groupName, newTrigger)) { NotifySchedulerThread(newTrigger.GetNextFireTimeUtc()); NotifySchedulerListenersUnscheduled(triggerName, groupName); NotifySchedulerListenersScheduled(newTrigger); } else { return null; } return ft; }
/// <summary> /// Add (register) the given <see cref="ICalendar" /> to the Scheduler. /// </summary> public virtual void AddCalendar(SchedulingContext ctxt, string calName, ICalendar calendar, bool replace, bool updateTriggers) { ValidateState(); resources.JobStore.StoreCalendar(ctxt, calName, calendar, replace, updateTriggers); }
/// <summary> /// Pause all of the <see cref="Trigger" />s in the given group. /// </summary> public virtual void PauseTriggerGroup(SchedulingContext ctxt, string groupName) { ValidateState(); if (groupName == null) { groupName = SchedulerConstants.DefaultGroup; } resources.JobStore.PauseTriggerGroup(ctxt, groupName); NotifySchedulerThread(null); NotifySchedulerListenersPausedTrigger(null, groupName); }
/// <summary> /// Delete the identified <see cref="ICalendar" /> from the Scheduler. /// </summary> /// <returns> true if the Calendar was found and deleted.</returns> public virtual bool DeleteCalendar(SchedulingContext ctxt, string calName) { ValidateState(); return resources.JobStore.RemoveCalendar(ctxt, calName); }
/// <summary> /// Construct a new <see cref="QuartzSchedulerThread" /> for the given /// <see cref="QuartzScheduler" /> as a <see cref="Thread" /> with the given /// attributes. /// </summary> internal QuartzSchedulerThread(QuartzScheduler qs, QuartzSchedulerResources qsRsrcs, SchedulingContext ctxt, bool setDaemon, int threadPrio) : base(qsRsrcs.ThreadName) { log = LogManager.GetLogger(GetType()); //ThreadGroup generatedAux = qs.SchedulerThreadGroup; this.qs = qs; this.qsRsrcs = qsRsrcs; this.ctxt = ctxt; IsBackground = setDaemon; Priority = (ThreadPriority)threadPrio; // start the underlying thread, but put this object into the 'paused' // state // so processing doesn't start yet... paused = true; halted = false; Start(); }
/// <summary> /// Get the <see cref="ICalendar" /> instance with the given name. /// </summary> public virtual ICalendar GetCalendar(SchedulingContext ctxt, string calName) { ValidateState(); return resources.JobStore.RetrieveCalendar(ctxt, calName); }
/// <summary> /// Create a JobRunShell instance with the given settings. /// </summary> /// <param name="jobRunShellFactory">A handle to the <see cref="IJobRunShellFactory" /> that produced /// this <see cref="JobRunShell" />.</param> /// <param name="scheduler">The <see cref="IScheduler" /> instance that should be made /// available within the <see cref="JobExecutionContext" />.</param> /// <param name="schdCtxt">the <see cref="SchedulingContext" /> that should be used by the /// <see cref="JobRunShell" /> when making updates to the <see cref="IJobStore" />.</param> public JobRunShell(IJobRunShellFactory jobRunShellFactory, IScheduler scheduler, SchedulingContext schdCtxt) { this.jobRunShellFactory = jobRunShellFactory; this.scheduler = scheduler; this.schdCtxt = schdCtxt; log = LogManager.GetLogger(GetType()); }
/// <summary> /// Get the names of all registered <see cref="ICalendar" />s. /// </summary> public virtual string[] GetCalendarNames(SchedulingContext ctxt) { ValidateState(); return resources.JobStore.GetCalendarNames(ctxt); }