예제 #1
0
        public TriggerFiredBundle TriggerFired(Trigger trigger)
        {
            lock (_triggerLock)
            {
                TriggerWrapper tw = _triggersDictionary[trigger.Name] as TriggerWrapper;
                // was the trigger deleted since being acquired?
                if (tw == null || tw.Trigger == null)
                    return null;
                // was the trigger completed since being acquired?
                if (tw.State == InternalTriggerState.Complete)
                    return null;
                // was the trigger paused since being acquired?
                if (tw.State == InternalTriggerState.Paused)
                    return null;
                // was the trigger blocked since being acquired?
                if (tw.State == InternalTriggerState.Blocked)
                    return null;
                // was the trigger paused and blocked since being acquired?
                if (tw.State == InternalTriggerState.PausedAndBlocked)
                    return null;

                NullableDateTime prevFireTime = trigger.GetPreviousFireTimeUtc();
                // in case trigger was replaced between acquiring and firering
                _timeTriggers.Remove(tw);
                trigger.Triggered();
                //tw.state = TriggerWrapper.StateExecuting;
                tw.State = InternalTriggerState.Waiting;

                IScheduledJob job = RetrieveJob(trigger.JobName);
                TriggerFiredBundle bndle = new TriggerFiredBundle(job, trigger, false, DateTime.UtcNow,
                                           trigger.GetPreviousFireTimeUtc(), prevFireTime, trigger.GetNextFireTimeUtc());

                NullableDateTime d = tw.Trigger.GetNextFireTimeUtc();
                if (d.HasValue)
                {
                    lock (_triggerLock)
                    {
                        _timeTriggers.Add(tw);
                    }
                }

                return bndle;
            }
        }
예제 #2
0
        /// <summary>
        /// The main processing loop.
        /// </summary>
        public void Run()
        {
            bool lastAcquireFailed = false;

            while (!_halted)
            {
                try
                {
                    // check if we're supposed to pause...
                    lock (_pauseLock)
                    {
                        while (_paused && !_halted)
                        {
                            try
                            {
                                // wait until togglePause(false) is called...
                                Monitor.Wait(_pauseLock, 100);
                            }
                            catch (ThreadInterruptedException)
                            {
                            }
                        }
                        if (_halted)
                        {
                            break;
                        }
                    }

                    int      availTreadCount = _threadPool.AvailableThreads;
                    DateTime now;
                    int      spinInterval;
                    int      numPauses;
                    if (availTreadCount > 0)
                    {
                        Trigger trigger = null;

                        now = DateTime.UtcNow;

                        _signaled = false;
                        try
                        {
                            trigger           = AcquireNextTrigger(now.AddMilliseconds(_idleWaitTime));
                            lastAcquireFailed = false;
                        }
                        catch (Exception e)
                        {
                            if (!lastAcquireFailed)
                            {
                                log.Error("SchedulerThreadLoop: RuntimeException " + e.Message, e);
                            }
                            lastAcquireFailed = true;
                        }

                        if (trigger != null)
                        {
                            now = DateTime.UtcNow;
                            DateTime triggerTime      = trigger.GetNextFireTimeUtc().Value;
                            long     timeUntilTrigger = (long)(triggerTime - now).TotalMilliseconds;
                            spinInterval = 10;

                            // this looping may seem a bit silly, but it's the
                            // current work-around
                            // for a dead-lock that can occur if the Thread.sleep()
                            // is replaced with
                            // a obj.wait() that gets notified when the signal is
                            // set...
                            // so to be able to detect the signal change without
                            // sleeping the entire
                            // timeUntilTrigger, we spin here... don't worry
                            // though, this spinning
                            // doesn't even register 0.2% cpu usage on a pentium 4.
                            numPauses = (int)(timeUntilTrigger / spinInterval);
                            while (numPauses >= 0 && !_signaled)
                            {
                                try
                                {
                                    Thread.Sleep(spinInterval);
                                }
                                catch (ThreadInterruptedException)
                                {
                                }

                                now = DateTime.UtcNow;
                                timeUntilTrigger = (long)(triggerTime - now).TotalMilliseconds;
                                numPauses        = (int)(timeUntilTrigger / spinInterval);
                            }
                            if (_signaled)
                            {
                                try
                                {
                                    ReleaseAcquiredTrigger(trigger);
                                }
                                catch (Exception ex)
                                {
                                    log.Error("ReleaseAcquiredTrigger: RuntimeException " + ex.Message, ex);
                                }
                                _signaled = false;
                                continue;
                            }

                            // set trigger to 'executing'
                            TriggerFiredBundle bundle = null;

                            lock (_pauseLock)
                            {
                                if (!_halted)
                                {
                                    try
                                    {
                                        bundle = TriggerFired(trigger);
                                    }
                                    catch (Exception ex)
                                    {
                                        log.Error(string.Format(CultureInfo.InvariantCulture, "RuntimeException while firing trigger {0}", trigger.Name), ex);
                                    }
                                }

                                // it's possible to get 'null' if the trigger was paused,
                                // blocked, or other similar occurances that prevent it being
                                // fired at this time...  or if the scheduler was shutdown (halted)
                                if (bundle == null)
                                {
                                    try
                                    {
                                        ReleaseAcquiredTrigger(trigger);
                                    }
                                    catch (SchedulerException)
                                    {
                                    }
                                    continue;
                                }

                                _threadPool.QueueUserWorkItem(new WaitCallback(ProcessJob), bundle);
                            }

                            continue;
                        }
                    }
                    else
                    {
                        // if(availTreadCount > 0)
                        continue; // should never happen, if threadPool.blockForAvailableThreads() follows contract
                    }

                    // this looping may seem a bit silly, but it's the current
                    // work-around
                    // for a dead-lock that can occur if the Thread.sleep() is replaced
                    // with
                    // a obj.wait() that gets notified when the signal is set...
                    // so to be able to detect the signal change without sleeping the
                    // entier
                    // getRandomizedIdleWaitTime(), we spin here... don't worry though,
                    // the
                    // CPU usage of this spinning can't even be measured on a pentium
                    // 4.
                    now = DateTime.UtcNow;
                    DateTime waitTime          = now.AddMilliseconds(GetRandomizedIdleWaitTime());
                    long     timeUntilContinue = (long)(waitTime - now).TotalMilliseconds;
                    spinInterval = 10;
                    numPauses    = (int)(timeUntilContinue / spinInterval);

                    while (numPauses > 0 && !_signaled)
                    {
                        try
                        {
                            Thread.Sleep(10);
                        }
                        catch (ThreadInterruptedException)
                        {
                        }
                        now = DateTime.UtcNow;
                        timeUntilContinue = (long)(waitTime - now).TotalMilliseconds;
                        numPauses         = (int)(timeUntilContinue / spinInterval);
                    }
                }
                catch (ThreadAbortException)
                {
                }
                catch (Exception ex)
                {
                    log.Error("Runtime error occured in main trigger firing loop.", ex);
                }
            }
        }