Ejemplo n.º 1
0
        /// <summary>
        /// Returns a list of Dates that are the next fire times of a
        /// <see cref="Trigger" />.
        /// The input trigger will be cloned before any work is done, so you need
        /// not worry about its state being altered by this method.
        /// </summary>
        /// <param name="trigg">The trigger upon which to do the work</param>
        /// <param name="cal">The calendar to apply to the trigger's schedule</param>
        /// <param name="numTimes">The number of next fire times to produce</param>
        /// <returns>List of java.util.Date objects</returns>
        public static IList ComputeFireTimes(Trigger trigg, ICalendar cal, int numTimes)
        {
            ArrayList lst = new ArrayList();

            Trigger t = (Trigger)trigg.Clone();

            if (t.GetNextFireTimeUtc() == null || !t.GetNextFireTimeUtc().HasValue)
            {
                t.ComputeFirstFireTimeUtc(cal);
            }

            for (int i = 0; i < numTimes; i++)
            {
                NullableDateTime d = t.GetNextFireTimeUtc();
                if (d.HasValue)
                {
                    lst.Add(d);
                    t.Triggered(cal);
                }
                else
                {
                    break;
                }
            }

            return(ArrayList.ReadOnly(new ArrayList(lst)));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Compare the next fire time of this <see cref="Trigger" /> to that of
        /// another.
        /// </summary>
        public virtual int CompareTo(object obj)
        {
            Trigger other = (Trigger)obj;

            NullableDateTime myTime    = GetNextFireTimeUtc();
            NullableDateTime otherTime = other.GetNextFireTimeUtc();

            if (!myTime.HasValue && !otherTime.HasValue)
            {
                return(0);
            }

            if (!myTime.HasValue)
            {
                return(1);
            }

            if (!otherTime.HasValue)
            {
                return(-1);
            }

            if ((myTime.Value < otherTime.Value))
            {
                return(-1);
            }

            if ((myTime.Value > otherTime.Value))
            {
                return(1);
            }

            return(0);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns a list of Dates that are the next fire times of a  <see cref="Trigger" />
        /// that fall within the given date range. The input trigger will be cloned
        /// before any work is done, so you need not worry about its state being
        /// altered by this method.
        /// <p>
        /// NOTE: if this is a trigger that has previously fired within the given
        /// date range, then firings which have already occured will not be listed
        /// in the output List.
        /// </p>
        /// </summary>
        /// <param name="trigg">The trigger upon which to do the work</param>
        /// <param name="cal">The calendar to apply to the trigger's schedule</param>
        /// <param name="from">The starting date at which to find fire times</param>
        /// <param name="to">The ending date at which to stop finding fire times</param>
        /// <returns>List of java.util.Date objects</returns>
        public static IList ComputeFireTimesBetween(Trigger trigg, ICalendar cal, DateTime from, DateTime to)
        {
            ArrayList lst = new ArrayList();

            Trigger t = (Trigger)trigg.Clone();

            if (t.GetNextFireTimeUtc() == null || !t.GetNextFireTimeUtc().HasValue)
            {
                t.StartTimeUtc = from;
                t.EndTimeUtc   = to;
                t.ComputeFirstFireTimeUtc(cal);
            }

            // TODO: this method could be more efficient by using logic specific
            //        to the type of trigger ...
            while (true)
            {
                NullableDateTime d = t.GetNextFireTimeUtc();
                if (d.HasValue)
                {
                    if (d.Value < from)
                    {
                        t.Triggered(cal);
                        continue;
                    }
                    if (d.Value > to)
                    {
                        break;
                    }
                    lst.Add(d);
                    t.Triggered(cal);
                }
                else
                {
                    break;
                }
            }
            return(ArrayList.ReadOnly(new ArrayList(lst)));
        }
        /// <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>
        /// 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> 
        /// 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;
        }
        private void DoUpdateOfMisfiredTrigger(ConnectionAndTransactionHolder conn, SchedulingContext ctxt, Trigger trig,
                                               bool forceState, string newStateIfNotComplete, bool recovering)
        {
            ICalendar cal = null;
            if (trig.CalendarName != null)
            {
                cal = RetrieveCalendar(conn, ctxt, trig.CalendarName);
            }

            signaler.NotifyTriggerListenersMisfired(trig);

            trig.UpdateAfterMisfire(cal);

            if (!trig.GetNextFireTimeUtc().HasValue)
            {
                StoreTrigger(conn, ctxt, trig, null, true, StateComplete, forceState, recovering);
            }
            else
            {
                StoreTrigger(conn, ctxt, trig, null, true, newStateIfNotComplete, forceState, false);
            }
        }
        protected virtual void TriggeredJobComplete(ConnectionAndTransactionHolder conn, SchedulingContext ctxt,
                                                             Trigger trigger,
                                                             JobDetail jobDetail, SchedulerInstruction triggerInstCode)
        {
            try
            {
                if (triggerInstCode == SchedulerInstruction.DeleteTrigger)
                {
                    if (!trigger.GetNextFireTimeUtc().HasValue)
                    {
                        // double check for possible reschedule within job 
                        // execution, which would cancel the need to delete...
                        TriggerStatus stat = Delegate.SelectTriggerStatus(conn, trigger.Name, trigger.Group);
                        if (stat != null && !stat.NextFireTimeUtc.HasValue)
                        {
                            RemoveTrigger(conn, ctxt, trigger.Name, trigger.Group);
                        }
                    }
                    else
                    {
                        RemoveTrigger(conn, ctxt, trigger.Name, trigger.Group);
                        signaler.SignalSchedulingChange(null);
                    }
                }
                else if (triggerInstCode == SchedulerInstruction.SetTriggerComplete)
                {
                    Delegate.UpdateTriggerState(conn, trigger.Name, trigger.Group, StateComplete);
                    signaler.SignalSchedulingChange(null);
                }
                else if (triggerInstCode == SchedulerInstruction.SetTriggerError)
                {
                    Log.Info("Trigger " + trigger.FullName + " set to ERROR state.");
                    Delegate.UpdateTriggerState(conn, trigger.Name, trigger.Group, StateError);
                    signaler.SignalSchedulingChange(null);
                }
                else if (triggerInstCode == SchedulerInstruction.SetAllJobTriggersComplete)
                {
                    Delegate.UpdateTriggerStatesForJob(conn, trigger.JobName, trigger.JobGroup, StateComplete);
                    signaler.SignalSchedulingChange(null);
                }
                else if (triggerInstCode == SchedulerInstruction.SetAllJobTriggersError)
                {
                    Log.Info("All triggers of Job " + trigger.FullJobName + " set to ERROR state.");
                    Delegate.UpdateTriggerStatesForJob(conn, trigger.JobName, trigger.JobGroup, StateError);
                    signaler.SignalSchedulingChange(null);
                }

                if (jobDetail.Stateful)
                {
                    Delegate.UpdateTriggerStatesForJobFromOtherState(conn, jobDetail.Name, jobDetail.Group,
                                                                     StateWaiting, StateBlocked);

                    Delegate.UpdateTriggerStatesForJobFromOtherState(conn, jobDetail.Name, jobDetail.Group,
                                                                     StatePaused,
                                                                     StatePausedBlocked);
                    signaler.SignalSchedulingChange(null);

                    try
                    {
                        if (jobDetail.JobDataMap.Dirty)
                        {
                            Delegate.UpdateJobData(conn, jobDetail);
                        }
                    }
                    catch (IOException e)
                    {
                        throw new JobPersistenceException("Couldn't serialize job data: " + e.Message, e);
                    }
                    catch (Exception e)
                    {
                        throw new JobPersistenceException("Couldn't update job data: " + e.Message, e);
                    }
                }
            }
            catch (Exception e)
            {
                throw new JobPersistenceException("Couldn't update trigger state(s): " + e.Message, e);
            }

            try
            {
                Delegate.DeleteFiredTrigger(conn, trigger.FireInstanceId);
            }
            catch (Exception e)
            {
                throw new JobPersistenceException("Couldn't delete fired trigger: " + e.Message, e);
            }
        }
        protected virtual TriggerFiredBundle TriggerFired(ConnectionAndTransactionHolder conn,
                                                                   SchedulingContext ctxt,
                                                                   Trigger trigger)
        {
            JobDetail job;
            ICalendar cal = null;

            // Make sure trigger wasn't deleted, paused, or completed...
            try
            {
                // if trigger was deleted, state will be StateDeleted
                String state = Delegate.SelectTriggerState(conn, trigger.Name, trigger.Group);
                if (!state.Equals(StateAcquired))
                {
                    return null;
                }
            }
            catch (Exception e)
            {
                throw new JobPersistenceException("Couldn't select trigger state: " + e.Message, e);
            }

            try
            {
                job = RetrieveJob(conn, ctxt, trigger.JobName, trigger.JobGroup);
                if (job == null)
                {
                    return null;
                }
            }
            catch (JobPersistenceException jpe)
            {
                try
                {
                    Log.Error("Error retrieving job, setting trigger state to ERROR.", jpe);
                    Delegate.UpdateTriggerState(conn, trigger.Name, trigger.Group, StateError);
                }
                catch (Exception sqle)
                {
                    Log.Error("Unable to set trigger state to ERROR.", sqle);
                }
                throw;
            }

            if (trigger.CalendarName != null)
            {
                cal = RetrieveCalendar(conn, ctxt, trigger.CalendarName);
                if (cal == null)
                {
                    return null;
                }
            }

            try
            {
                Delegate.DeleteFiredTrigger(conn, trigger.FireInstanceId);
                Delegate.InsertFiredTrigger(conn, trigger, StateExecuting, job);
            }
            catch (Exception e)
            {
                throw new JobPersistenceException("Couldn't insert fired trigger: " + e.Message, e);
            }

            NullableDateTime prevFireTime = trigger.GetPreviousFireTimeUtc();

            // call triggered - to update the trigger's next-fire-time state...
            trigger.Triggered(cal);

            String state2 = StateWaiting;
            bool force = true;

            if (job.Stateful)
            {
                state2 = StateBlocked;
                force = false;
                try
                {
                    Delegate.UpdateTriggerStatesForJobFromOtherState(conn, job.Name, job.Group, StateBlocked,
                                                                     StateWaiting);
                    Delegate.UpdateTriggerStatesForJobFromOtherState(conn, job.Name, job.Group, StateBlocked,
                                                                     StateAcquired);
                    Delegate.UpdateTriggerStatesForJobFromOtherState(conn, job.Name, job.Group, StatePausedBlocked,
                                                                     StatePaused);
                }
                catch (Exception e)
                {
                    throw new JobPersistenceException("Couldn't update states of blocked triggers: " + e.Message, e);
                }
            }

            if (!trigger.GetNextFireTimeUtc().HasValue)
            {
                state2 = StateComplete;
                force = true;
            }

            StoreTrigger(conn, ctxt, trigger, job, true, state2, force, false);

            job.JobDataMap.ClearDirtyFlag();

            return new TriggerFiredBundle(
                job, 
                trigger, 
                cal, 
                trigger.Group.Equals(SchedulerConstants.DefaultRecoveryGroup),
                DateTime.UtcNow,
                trigger.GetPreviousFireTimeUtc(), 
                prevFireTime, 
                trigger.GetNextFireTimeUtc());
        }
Ejemplo n.º 10
0
 private static DateTime? GetNextRunDate(Trigger trigger)
 {
     var nextFire = trigger.GetNextFireTimeUtc();
     return nextFire == null ? (DateTime?) null : nextFire.Value.ToLocalTime();
 }
        //---------------------------------------------------------------------------
        // 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;
            }
        }
        /// <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();
            }
        }
        /// <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;
        }