aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick J Cherry <patrick@bytemark.co.uk>2012-07-03 15:26:51 +0100
committerPatrick J Cherry <patrick@bytemark.co.uk>2012-07-03 15:26:51 +0100
commit5bfb713e39fde3778f57cb33f90157fc870bf64b (patch)
treeb8bbb095916a935471a2c7d16e19c263c15989c1
parent4153ce040ccc82421865438a32fe7e17d9739ac6 (diff)
Removed ability to freeze threads, since that is not used any more.
Added checks to make sure threads are run at least every two minutes.
-rw-r--r--lib/mauve/http_server.rb7
-rw-r--r--lib/mauve/mauve_thread.rb106
-rw-r--r--lib/mauve/pop3_server.rb9
-rw-r--r--lib/mauve/server.rb6
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