Example #1
0
        /// <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);
        }
Example #2
0
        /// <summary>
        /// Create a JobExcecutionContext with the given context data.
        /// </summary>
        public JobExecutionContext(IScheduler scheduler, TriggerFiredBundle firedBundle, IJob job)
        {
            this.scheduler = scheduler;
            trigger = firedBundle.Trigger;
            calendar = firedBundle.Calendar;
            jobDetail = firedBundle.JobDetail;
            this.job = job;
            recovering = firedBundle.Recovering;
            fireTimeUtc = firedBundle.FireTimeUtc;
            scheduledFireTimeUtc = firedBundle.ScheduledFireTimeUtc;
            prevFireTimeUtc = firedBundle.PrevFireTimeUtc;
            nextFireTimeUtc = firedBundle.NextFireTimeUtc;

            jobDataMap = new JobDataMap();
            jobDataMap.PutAll(jobDetail.JobDataMap);
            jobDataMap.PutAll(trigger.JobDataMap);
        }
Example #3
0
 /// <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);
 }
Example #4
0
        /// <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;
        }
Example #5
0
        /// <summary>
        /// Select the JobDetail object for a given job name / group name.
        /// </summary>
        /// <param name="conn">The DB Connection.</param>
        /// <param name="jobName">The job name whose listeners are wanted.</param>
        /// <param name="groupName">The group containing the job.</param>
        /// <param name="loadHelper">The load helper.</param>
        /// <returns>The populated JobDetail object.</returns>
        public virtual JobDetail SelectJobDetail(ConnectionAndTransactionHolder conn, string jobName, string groupName,
                                                 ITypeLoadHelper loadHelper)
        {
            using (IDbCommand cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlSelectJobDetail)))
            {
                AddCommandParameter(cmd, 1, "jobName", jobName);
                AddCommandParameter(cmd, 2, "jobGroup", groupName);
                using (IDataReader rs = cmd.ExecuteReader())
                {
                    JobDetail job = null;

                    if (rs.Read())
                    {
                        job = new JobDetail();

                        job.Name = GetString(rs[ColumnJobName]);
                        job.Group = GetString(rs[ColumnJobGroup]);
                        job.Description = GetString(rs[ColumnDescription]);
                        job.JobType = loadHelper.LoadType(GetString(rs[ColumnJobClass]));
                        job.Durable = GetBoolean(rs[ColumnIsDurable]);
                        job.Volatile = GetBoolean(rs[ColumnIsVolatile]);
                        job.RequestsRecovery = GetBoolean(rs[ColumnRequestsRecovery]);

                        IDictionary map;
                        if (CanUseProperties)
                        {
                            map = GetMapFromProperties(rs, 8);
                        }
                        else
                        {
                            map = (IDictionary)GetObjectFromBlob(rs, 8);
                        }

                        if (null != map)
                        {
                            job.JobDataMap = new JobDataMap(map);
                        }
                    }

                    return job;
                }
            }
        }
Example #6
0
        //---------------------------------------------------------------------------
        // triggers
        //---------------------------------------------------------------------------

        /// <summary>
        /// Insert the base trigger data.
        /// </summary>
        /// <param name="conn">the DB Connection</param>
        /// <param name="trigger">the trigger to insert</param>
        /// <param name="state">the state that the trigger should be stored in</param>
        /// <param name="jobDetail">The job detail.</param>
        /// <returns>the number of rows inserted</returns>
        public virtual int InsertTrigger(ConnectionAndTransactionHolder conn, Trigger trigger, string state,
                                         JobDetail jobDetail)
        {
            byte[] baos = null;
            if (trigger.JobDataMap.Count > 0)
            {
                baos = SerializeJobData(trigger.JobDataMap);
            }

            using (IDbCommand cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlInsertTrigger)))
            {
                AddCommandParameter(cmd, 1, "triggerName", trigger.Name);
                AddCommandParameter(cmd, 2, "triggerGroup", trigger.Group);
                AddCommandParameter(cmd, 3, "triggerJobName", trigger.JobName);
                AddCommandParameter(cmd, 4, "triggerJobGroup", trigger.JobGroup);
                AddCommandParameter(cmd, 5, "triggerVolatile", GetDbBooleanValue(trigger.Volatile));
                AddCommandParameter(cmd, 6, "triggerDescription", trigger.Description);
                
                if (trigger.GetNextFireTimeUtc().HasValue)
                {
                    AddCommandParameter(cmd, 7, "triggerNextFireTime",
                                    Convert.ToDecimal(trigger.GetNextFireTimeUtc().Value.Ticks));
                }
                else
                {
                    AddCommandParameter(cmd, 7, "triggerNextFireTime", null);
                }
                long prevFireTime = -1;
                if (trigger.GetPreviousFireTimeUtc().HasValue)
                {
                    prevFireTime = trigger.GetPreviousFireTimeUtc().Value.Ticks;
                }
                AddCommandParameter(cmd, 8, "triggerPreviousFireTime", Convert.ToDecimal(prevFireTime));
                AddCommandParameter(cmd, 9, "triggerState", state);
                string paramName = "triggerType";
                if (trigger is SimpleTrigger && !trigger.HasAdditionalProperties)
                {
                    AddCommandParameter(cmd, 10, paramName, TriggerTypeSimple);
                }
                else if (trigger is CronTrigger && !trigger.HasAdditionalProperties)
                {
                    AddCommandParameter(cmd, 10, paramName, TriggerTypeCron);
                }
                else
                {
                    // (trigger instanceof BlobTrigger or additional properties in sub-class
                    AddCommandParameter(cmd, 10, paramName, TriggerTypeBlob);
                }
                AddCommandParameter(cmd, 11, "triggerStartTime", Convert.ToDecimal(trigger.StartTimeUtc.Ticks));
                long endTime = 0;
                if (trigger.EndTimeUtc.HasValue)
                {
                    endTime = trigger.EndTimeUtc.Value.Ticks;
                }
                AddCommandParameter(cmd, 12, "triggerEndTime", Convert.ToDecimal(endTime));
                AddCommandParameter(cmd, 13, "triggerCalendarName", trigger.CalendarName);
                AddCommandParameter(cmd, 14, "triggerMisfireInstruction", trigger.MisfireInstruction);

                paramName = "triggerJobJobDataMap";
                if (baos != null)
                {
                    AddCommandParameter(cmd, 15, paramName, baos, dbProvider.Metadata.DbBinaryType);
                }
                else
                {
                    AddCommandParameter(cmd, 15, paramName, null, dbProvider.Metadata.DbBinaryType);
                }
                AddCommandParameter(cmd, 16, "triggerPriority", trigger.Priority);

                int insertResult = cmd.ExecuteNonQuery();
                if (insertResult > 0)
                {
                    string[] trigListeners = trigger.TriggerListenerNames;
                    for (int i = 0; trigListeners != null && i < trigListeners.Length; i++)
                    {
                        InsertTriggerListener(conn, trigger, trigListeners[i]);
                    }
                }

                return insertResult;
            }
        }
Example #7
0
        /// <summary>
        /// Update the job data map for the given job.
        /// </summary>
        /// <param name="conn">The conn.</param>
        /// <param name="job">the job to update</param>
        /// <returns>the number of rows updated</returns>
        public virtual int UpdateJobData(ConnectionAndTransactionHolder conn, JobDetail job)
        {
            byte[] baos = SerializeJobData(job.JobDataMap);

            using (IDbCommand cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlUpdateJobData)))
            {
                AddCommandParameter(cmd, 1, "jobDataMap", baos, dbProvider.Metadata.DbBinaryType);
                AddCommandParameter(cmd, 2, "jobName", job.Name);
                AddCommandParameter(cmd, 3, "jobGroup", job.Group);

                return cmd.ExecuteNonQuery();
            }
        }
Example #8
0
        /// <summary>
        /// Associate a listener with a job.
        /// </summary>
        /// <param name="conn">The DB Connection.</param>
        /// <param name="job">The job to associate with the listener.</param>
        /// <param name="listener">The listener to insert.</param>
        /// <returns>The number of rows inserted.</returns>
        public virtual int InsertJobListener(ConnectionAndTransactionHolder conn, JobDetail job, string listener)
        {
            using (IDbCommand cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlInsertJobListener)))
            {
                AddCommandParameter(cmd, 1, "jobName", job.Name);
                AddCommandParameter(cmd, 2, "jobGroup", job.Group);
                AddCommandParameter(cmd, 3, "listener", listener);

                return cmd.ExecuteNonQuery();
            }
        }
Example #9
0
        /// <summary>
        /// Insert a fired trigger.
        /// </summary>
        /// <param name="conn">the DB Connection</param>
        /// <param name="trigger">the trigger</param>
        /// <param name="state">the state that the trigger should be stored in</param>
        /// <param name="job">The job.</param>
        /// <returns>the number of rows inserted</returns>
        public virtual int InsertFiredTrigger(ConnectionAndTransactionHolder conn, Trigger trigger, string state,
                                              JobDetail job)
        {
            using (IDbCommand cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlInsertFiredTrigger)))
            {
                AddCommandParameter(cmd, 1, "triggerEntryId", trigger.FireInstanceId);
                AddCommandParameter(cmd, 2, "triggerName", trigger.Name);
                AddCommandParameter(cmd, 3, "triggerGroup", trigger.Group);
                AddCommandParameter(cmd, 4, "triggerVolatile", GetDbBooleanValue(trigger.Volatile));
                AddCommandParameter(cmd, 5, "triggerInstanceName", instanceId);
                AddCommandParameter(cmd, 6, "triggerFireTime",
                                    Convert.ToDecimal(trigger.GetNextFireTimeUtc().Value.Ticks));
                AddCommandParameter(cmd, 7, "triggerState", state);
                if (job != null)
                {
                    AddCommandParameter(cmd, 8, "triggerJobName", trigger.JobName);
                    AddCommandParameter(cmd, 9, "triggerJobGroup", trigger.JobGroup);
                    AddCommandParameter(cmd, 10, "triggerJobStateful", GetDbBooleanValue(job.Stateful));
                    AddCommandParameter(cmd, 11, "triggerJobRequestsRecovery", GetDbBooleanValue(job.RequestsRecovery));
                }
                else
                {
                    AddCommandParameter(cmd, 8, "triggerJobName", null);
                    AddCommandParameter(cmd, 9, "triggerJobGroup", null);
                    AddCommandParameter(cmd, 10, "triggerJobStateful", GetDbBooleanValue(false));
                    AddCommandParameter(cmd, 11, "triggerJobRequestsRecovery", GetDbBooleanValue(false));
                }

                AddCommandParameter(cmd, 12, "triggerPriority", trigger.Priority);

                return cmd.ExecuteNonQuery();
            }
        }
Example #10
0
        /// <summary>
        /// Update the job detail record.
        /// </summary>
        /// <param name="conn">The DB Connection.</param>
        /// <param name="job">The job to update.</param>
        /// <returns>Number of rows updated.</returns>
        public virtual int UpdateJobDetail(ConnectionAndTransactionHolder conn, JobDetail job)
        {
            byte[] baos = SerializeJobData(job.JobDataMap);

            using (IDbCommand cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlUpdateJobDetail)))
            {
                AddCommandParameter(cmd, 1, "jobDescription", job.Description);
                AddCommandParameter(cmd, 2, "jobType", GetStorableJobTypeName(job.JobType));
                AddCommandParameter(cmd, 3, "jobDurable", GetDbBooleanValue(job.Durable));
                AddCommandParameter(cmd, 4, "jobVolatile", GetDbBooleanValue(job.Volatile));
                AddCommandParameter(cmd, 5, "jobStateful", GetDbBooleanValue(job.Stateful));
                AddCommandParameter(cmd, 6, "jobRequestsRecovery", GetDbBooleanValue(job.RequestsRecovery));
                AddCommandParameter(cmd, 7, "jobDataMap", baos, dbProvider.Metadata.DbBinaryType);
                AddCommandParameter(cmd, 8, "jobName", job.Name);
                AddCommandParameter(cmd, 9, "jobGroup", job.Group);

                int insertResult = cmd.ExecuteNonQuery();

                if (insertResult > 0)
                {
                    DeleteJobListeners(conn, job.Name, job.Group);

                    String[] jobListeners = job.JobListenerNames;
                    for (int i = 0; jobListeners != null && i < jobListeners.Length; i++)
                    {
                        InsertJobListener(conn, job, jobListeners[i]);
                    }
                }

                return insertResult;
            }
        }
Example #11
0
        /// <summary>
        /// Select the job to which the trigger is associated.
        /// </summary>
        /// <param name="conn">the DB Connection</param>
        /// <param name="triggerName">the name of the trigger</param>
        /// <param name="groupName">the group containing the trigger</param>
        /// <param name="loadHelper">The load helper.</param>
        /// <returns>The <see cref="JobDetail" /> object associated with the given trigger</returns>
        public virtual JobDetail SelectJobForTrigger(ConnectionAndTransactionHolder conn, string triggerName,
                                                     string groupName,
                                                     ITypeLoadHelper loadHelper)
        {
            using (IDbCommand cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlSelectJobForTrigger)))
            {
                AddCommandParameter(cmd, 1, "triggerName", triggerName);
                AddCommandParameter(cmd, 2, "triggerGroup", groupName);
                using (IDataReader rs = cmd.ExecuteReader())
                {
                    if (rs.Read())
                    {
                        JobDetail job = new JobDetail();
                        job.Name = GetString(rs[0]);
                        job.Group = GetString(rs[1]);
                        job.Durable = GetBoolean(rs[2]);
                        job.JobType = loadHelper.LoadType(GetString(rs[3]));
                        job.RequestsRecovery = GetBoolean(rs[4]);

                        return job;
                    }
                    else
                    {
                        if (logger.IsDebugEnabled)
                        {
                            logger.Debug("No job for trigger '" + groupName + "." + triggerName + "'.");
                        }
                        return null;
                    }
                }
            }
        }
Example #12
0
        /// <summary>
        /// Update the base trigger data.
        /// </summary>
        /// <param name="conn">The DB Connection.</param>
        /// <param name="trigger">The trigger to insert.</param>
        /// <param name="state">The state that the trigger should be stored in.</param>
        /// <param name="jobDetail">The job detail.</param>
        /// <returns>The number of rows updated.</returns>
        public virtual int UpdateTrigger(ConnectionAndTransactionHolder conn, Trigger trigger, string state,
                                         JobDetail jobDetail)
        {
            // save some clock cycles by unnecessarily writing job data blob ...
            bool updateJobData = trigger.JobDataMap.Dirty;
            byte[] baos = null;
            if (updateJobData && trigger.JobDataMap.Count > 0)
            {
                baos = SerializeJobData(trigger.JobDataMap);
            }

            IDbCommand cmd;

            int insertResult;

            if (updateJobData)
            {
                cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlUpdateTrigger));
            }
            else
            {
                cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlUpdateTriggerSkipData));
            }

            AddCommandParameter(cmd, 1, "triggerJobName", trigger.JobName);
            AddCommandParameter(cmd, 2, "triggerJobGroup", trigger.JobGroup);
            AddCommandParameter(cmd, 3, "triggerVolatile", GetDbBooleanValue(trigger.Volatile));
            AddCommandParameter(cmd, 4, "triggerDescription", trigger.Description);
            long nextFireTime = -1;

            if (trigger.GetNextFireTimeUtc().HasValue)
            {
                nextFireTime = trigger.GetNextFireTimeUtc().Value.Ticks;
            }
            AddCommandParameter(cmd, 5, "triggerNextFireTime", Convert.ToDecimal(nextFireTime));
            long prevFireTime = -1;

            if (trigger.GetPreviousFireTimeUtc().HasValue)
            {
                prevFireTime = trigger.GetPreviousFireTimeUtc().Value.Ticks;
            }
            AddCommandParameter(cmd, 6, "triggerPreviousFireTime", Convert.ToDecimal(prevFireTime));
            AddCommandParameter(cmd, 7, "triggerState", state);
            string paramName = "triggerType";
            if (trigger is SimpleTrigger && !trigger.HasAdditionalProperties)
            {
                // UpdateSimpleTrigger(conn, (SimpleTrigger)trigger);
                AddCommandParameter(cmd, 8, paramName, TriggerTypeSimple);
            }
            else if (trigger is CronTrigger && !trigger.HasAdditionalProperties)
            {
                // UpdateCronTrigger(conn, (CronTrigger)trigger);
                AddCommandParameter(cmd, 8, paramName, TriggerTypeCron);
            }
            else
            {
                // UpdateBlobTrigger(conn, trigger);
                AddCommandParameter(cmd, 8, paramName, TriggerTypeBlob);
            }

            AddCommandParameter(cmd, 9, "triggerStartTime", Convert.ToDecimal(trigger.StartTimeUtc.Ticks));
            long endTime = 0;
            if (trigger.EndTimeUtc.HasValue)
            {
                endTime = trigger.EndTimeUtc.Value.Ticks;
            }
            AddCommandParameter(cmd, 10, "triggerEndTime", Convert.ToDecimal(endTime));
            AddCommandParameter(cmd, 11, "triggerCalendarName", trigger.CalendarName);
            AddCommandParameter(cmd, 12, "triggerMisfireInstruction", trigger.MisfireInstruction);
            AddCommandParameter(cmd, 13, "triggerPriority", trigger.Priority);
            paramName = "triggerJobJobDataMap";
            if (updateJobData)
            {
                if (baos != null)
                {
                    AddCommandParameter(cmd, 14, paramName, baos, dbProvider.Metadata.DbBinaryType);
                }
                else
                {
                    AddCommandParameter(cmd, 14, paramName, null, dbProvider.Metadata.DbBinaryType);
                }
                AddCommandParameter(cmd, 15, "triggerName", trigger.Name);
                AddCommandParameter(cmd, 16, "triggerGroup", trigger.Group);
            }
            else
            {
                AddCommandParameter(cmd, 14, "triggerName", trigger.Name);
                AddCommandParameter(cmd, 15, "triggerGroup", trigger.Group);
            }

            insertResult = cmd.ExecuteNonQuery();

            if (insertResult > 0)
            {
                DeleteTriggerListeners(conn, trigger.Name, trigger.Group);

                String[] trigListeners = trigger.TriggerListenerNames;
                for (int i = 0; trigListeners != null && i < trigListeners.Length; i++)
                {
                    InsertTriggerListener(conn, trigger, trigListeners[i]);
                }
            }

            return insertResult;
        }
Example #13
0
 /// <summary>
 /// Checks equality between given job detail and this instance.
 /// </summary>
 /// <param name="detail">The detail to compare this instance with.</param>
 /// <returns></returns>
 public bool Equals(JobDetail detail)
 {
     return IsEqual(detail);
 }
Example #14
0
		/// <summary>
		/// Determines whether the specified detail is equal to this instance.
		/// </summary>
		/// <param name="detail">The detail to examine.</param>
		/// <returns>
		/// 	<c>true</c> if the specified detail is equal; otherwise, <c>false</c>.
		/// </returns>
        protected virtual bool IsEqual(JobDetail detail)
        {
			//doesn't consider job's saved data,
			//durability etc
            return (detail != null) && (detail.Name == Name) && (detail.Group == Group) &&
                   (detail.JobType == JobType);
        }
		/// <summary> <p>
		/// Create a <see cref="ObjectAlreadyExistsException" /> and auto-generate a
		/// message using the name/group from the given <see cref="JobDetail" />.
		/// </p>
		/// 
		/// <p>
		/// The message will read: <br />"Unable to store Job with name: '__' and
		/// group: '__', because one already exists with this identification."
		/// </p>
		/// </summary>
		public ObjectAlreadyExistsException(JobDetail offendingJob)
			: base(
				string.Format(CultureInfo.InvariantCulture, "Unable to store Job with name: '{0}' and group: '{1}', because one already exists with this identification.", offendingJob.Name, offendingJob.Group))
		{
		}