aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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