diff options
-rw-r--r-- | lib/mauve/http_server.rb | 7 | ||||
-rw-r--r-- | lib/mauve/mauve_thread.rb | 106 | ||||
-rw-r--r-- | lib/mauve/pop3_server.rb | 9 | ||||
-rw-r--r-- | lib/mauve/server.rb | 6 |
4 files changed, 36 insertions, 92 deletions
diff --git a/lib/mauve/http_server.rb b/lib/mauve/http_server.rb index 9250b2e..54dbe14 100644 --- a/lib/mauve/http_server.rb +++ b/lib/mauve/http_server.rb @@ -204,6 +204,13 @@ module Mauve super end + # + # Since Server.start doesn't return below, we can't check when the thread was last polled. + # + def last_polled_at + Time.now + end + private # diff --git a/lib/mauve/mauve_thread.rb b/lib/mauve/mauve_thread.rb index 42f41a2..dd5b47e 100644 --- a/lib/mauve/mauve_thread.rb +++ b/lib/mauve/mauve_thread.rb @@ -6,21 +6,14 @@ module Mauve # # This is a class to wrap our threads that have processing loops. # - # The thread is kept in a wrapper to allow it to be frozen and thawed at - # convenient times. - # class MauveThread # - # The sleep interval between runs of the main loop. Defaults to 5 seconds. - # - attr_reader :poll_every - - # # Set the thread up # def initialize @thread = nil + @last_polled_at = nil end # @return [Log4r::Logger] @@ -28,41 +21,19 @@ module Mauve @logger ||= Log4r::Logger.new(self.class.to_s) end - # Set the sleep interval between runs of the main loop. This can be - # anything greater than or equal to zero. If a number less than zero gets - # entered, it will be increased to zero. - # - # @param [Numeric] i The number of seconds to sleep - # @raise [ArgumentError] If +i+ is not numeric - # @return [Numeric] - # - def poll_every=(i) - raise ArgumentError.new("poll_every must be numeric") unless i.is_a?(Numeric) - # - # Set the minimum poll frequency. - # - if i.to_f < 0 - logger.debug "Increasing thread polling interval to 0s from #{i}" - i = 0 - end - - @poll_every = i - end - # This determines if a thread should stop # # @return [Boolean] def should_stop? - [:freezing, :stopping].include?(self.state) + self.state == :stopping end # This is the current state of the thread. It can be one of - # [:stopped, :starting, :started, :freezing, :frozen, :stopping, :killing, :killed] + # [:stopped, :starting, :started, :stopping, :killing, :killed] # # If the thread is not alive it will be +:stopped+. # - # @return [Symbol] One of [:stopped, :starting, :started, :freezing, - # :frozen, :stopping, :killing, :killed] + # @return [Symbol] One of [:stopped, :starting, :started, :stopping, :killing, :killed] def state if self.alive? @thread.key?(:state) ? @thread[:state] : :unknown @@ -74,14 +45,13 @@ module Mauve # This sets the state of a thread. It also records the last time the # thread changed status. # - # @param [Symbol] s One of [:stopped, :starting, :started, :freezing, - # :frozen, :stopping, :killing, :killed] + # @param [Symbol] s One of [:stopped, :starting, :started, :stopping, :killing, :killed] # @raise [ArgumentError] if +s+ is not a valid symbol or the thread is not # ready # @return [Symbol] the current thread state. # def state=(s) - raise ArgumentError, "Bad state for mauve_thread #{s.inspect}" unless [:stopped, :starting, :started, :freezing, :frozen, :stopping, :killing, :killed].include?(s) + raise ArgumentError, "Bad state for mauve_thread #{s.inspect}" unless [:stopped, :starting, :started, :stopping, :killing, :killed].include?(s) raise ArgumentError, "Thread not ready yet." unless @thread.is_a?(Thread) unless @thread[:state] == s @@ -104,23 +74,6 @@ module Mauve end end - # This asks the thread to freeze at the next opportunity. - # - def freeze - self.state = :freezing - - 20.times { Kernel.sleep 0.2 ; break if @thread.stop? } - - logger.warn("Thread has not frozen!") unless @thread.stop? - end - - # This returns true if the thread has frozen successfully. - # - # @return [Boolean] - def frozen? - self.stop? and self.state == :frozen - end - # This starts the thread. It wakes it up if it is alive, or starts it from # fresh if it is dead. # @@ -216,59 +169,36 @@ module Mauve @thread end + # + # Returns the time the thread loop was last run, or nil if it has never run. + # + def last_polled_at + @last_polled_at + end private - # This is the main run loop for the thread. In here are all the calls - # allowing use to freeze and thaw the thread neatly. + # This is the main run loop for the thread. # # This thread will run untill the thread state is changed to :stopping. # - def run_thread(interval = 5.0) + def run_thread # # Good to go. # @thread = Thread.current self.state = :starting - @poll_every ||= interval - # - # Make sure we get a number. - # - @poll_every = 5 unless @poll_every.is_a?(Numeric) - - rate_limit = 0.1 - while self.state != :stopping do - - self.state = :started if self.state == :starting - - # - # Schtop! - # - if self.state == :freezing - self.state = :frozen - Thread.stop - self.state = :started - end - - yield_start = Time.now.to_f + self.state = :started + @last_polled_at = Time.now yield # - # Ah-ha! Sleep with a break clause. Make sure we poll every @poll_every seconds. + # This is a little sleep to stop cpu hogging. # - ((@poll_every.to_f - Time.now.to_f + yield_start.to_f)/rate_limit). - round.to_i.times do - - break if self.should_stop? - - # - # This is a rate-limiting step - # - Kernel.sleep rate_limit - end + Kernel.sleep 0.001 end self.state = :stopped diff --git a/lib/mauve/pop3_server.rb b/lib/mauve/pop3_server.rb index 861b719..971adae 100644 --- a/lib/mauve/pop3_server.rb +++ b/lib/mauve/pop3_server.rb @@ -76,10 +76,17 @@ module Mauve super end + # + # Since Server.start doesn't return below, we can't check when the thread was last polled. + # + def last_polled_at + Time.now + end + private # - # This tarts the server, and keeps it going. + # This starts the server, and keeps it going. # def main_loop unless @server and @server.running? diff --git a/lib/mauve/server.rb b/lib/mauve/server.rb index 4a496b5..630a201 100644 --- a/lib/mauve/server.rb +++ b/lib/mauve/server.rb @@ -246,10 +246,10 @@ module Mauve thread_list.delete(klass.instance.thread) # - # Make sure that if the thread is frozen, that we've not been frozen for too long. + # Check every couple of minutes that the thread is still running. # - if klass.instance.state != :started and klass.instance.last_state_change.is_a?(Time) and klass.instance.last_state_change < (Time.now - 2.minutes) - logger.warn "#{klass} has been #{klass.instance.state} since #{klass.instance.last_state_change}. Killing and restarting." + if klass.instance.state == :started and klass.instance.last_polled_at.is_a?(Time) and klass.instance.last_polled_at < (Time.now - 2.minutes) + logger.warn "#{klass} has not run its loop since #{klass.instance.last_polled_at}. Killing and restarting." klass.instance.stop end |