about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2015-05-27 21:59:31 +0000
committerEric Wong <e@80x24.org>2015-05-27 21:59:31 +0000
commit5429893629154e39e0db33f5c98e237b29c7bbdc (patch)
tree9d6bc5f45869e3b433e0425e3f56656c8813e647
parent44dd54e3c3ae6a771baa17935ebe09ece1616026 (diff)
downloadmogilefs-client-5429893629154e39e0db33f5c98e237b29c7bbdc.tar.gz
The monotonic clock is immune to discontinuous time jumps while
still taking into account clock imperfections, making it appropriate
for calculating time differences and timeouts.
-rw-r--r--lib/mogilefs.rb10
-rw-r--r--lib/mogilefs/backend.rb14
-rw-r--r--lib/mogilefs/http_reader.rb4
-rw-r--r--lib/mogilefs/mogilefs.rb2
-rw-r--r--lib/mogilefs/mysql.rb14
-rw-r--r--lib/mogilefs/new_file/common.rb2
6 files changed, 30 insertions, 16 deletions
diff --git a/lib/mogilefs.rb b/lib/mogilefs.rb
index dd60e91..6059836 100644
--- a/lib/mogilefs.rb
+++ b/lib/mogilefs.rb
@@ -5,6 +5,16 @@
 # Client usage information is available in MogileFS::MogileFS.
 module MogileFS
 
+  if defined?(Process::CLOCK_MONOTONIC)
+    def self.now
+      Process.clock_gettime(Process::CLOCK_MONOTONIC)
+    end
+  else
+    def self.now
+      Time.now.to_f
+    end
+  end
+
   # Standard error class for most MogileFS-specific errors
   class Error < StandardError; end
 
diff --git a/lib/mogilefs/backend.rb b/lib/mogilefs/backend.rb
index 48f3a2e..01203f6 100644
--- a/lib/mogilefs/backend.rb
+++ b/lib/mogilefs/backend.rb
@@ -147,7 +147,7 @@ class MogileFS::Backend
       tries ||= Hash.new { |hash,host| hash[host] = 0 }
       nr = tries[@active_host] += 1
       if nr >= 2
-        @dead[@active_host] = [ Time.now, err ]
+        @dead[@active_host] = [ MogileFS.now, err ]
       end
       shutdown_unlocked
       retry
@@ -163,7 +163,7 @@ class MogileFS::Backend
   end
 
   def timeout_update(timeout, t0) # :nodoc:
-    timeout -= (Time.now - t0)
+    timeout -= (MogileFS.now - t0)
     timeout < 0 ? 0 : timeout
   end
 
@@ -174,12 +174,12 @@ class MogileFS::Backend
   def pipeline_drain_unlocked(io, timeout) # :nodoc:
     set = [ io ]
     while @pending.size > 0
-      t0 = Time.now
+      t0 = MogileFS.now
       r = IO.select(set, set, nil, timeout)
       timeout = timeout_update(timeout, t0)
 
       if r && r[0][0]
-        t0 = Time.now
+        t0 = MogileFS.now
         pipeline_gets_unlocked(io, timeout)
         timeout = timeout_update(timeout, t0)
       else
@@ -207,7 +207,7 @@ class MogileFS::Backend
         io.timed_write(request, timeout)
         @pending << [ request, block ]
       rescue SystemCallError, MogileFS::RequestTruncatedError => err
-        @dead[@active_host] = [ Time.now, err ]
+        @dead[@active_host] = [ MogileFS.now, err ]
         shutdown_unlocked(@pending[0])
         io = socket
         retry
@@ -343,14 +343,14 @@ class MogileFS::Backend
     return @socket if @socket and not @socket.closed?
 
     @hosts.shuffle.each do |host|
-      next if dead = @dead[host] and dead[0] > (Time.now - @fail_timeout)
+      next if dead = @dead[host] and dead[0] > (MogileFS.now - @fail_timeout)
 
       begin
         addr, port = host.split(/:/)
         @socket = MogileFS::Socket.tcp(addr, port, @timeout)
         @active_host = host
       rescue SystemCallError, MogileFS::Timeout => err
-        @dead[host] = [ Time.now, err ]
+        @dead[host] = [ MogileFS.now, err ]
         next
       end
 
diff --git a/lib/mogilefs/http_reader.rb b/lib/mogilefs/http_reader.rb
index e6b037d..bd3713c 100644
--- a/lib/mogilefs/http_reader.rb
+++ b/lib/mogilefs/http_reader.rb
@@ -46,13 +46,13 @@ class MogileFS::HTTPReader < MogileFS::Socket
   # body of the response.
   def self.try(path, timeout, range) # :nodoc:
     uri = URI.parse(path)
-    expire_at = Time.now + timeout
+    expire_at = MogileFS.now + timeout
     sock = tcp(uri.host, uri.port, timeout)
     buf = "GET #{uri.request_uri} HTTP/1.0\r\n#{range}\r\n" # no chunking
     sock.timed_write(buf, timeout)
 
     begin
-      raise MogileFS::Timeout if Time.now > expire_at
+      raise MogileFS::Timeout if MogileFS.now > expire_at
       sock.timed_peek(2048, buf, timeout) or
         raise MogileFS::InvalidResponseError, "EOF while reading header", []
     end until /\r\n\r\n/ =~ buf
diff --git a/lib/mogilefs/mogilefs.rb b/lib/mogilefs/mogilefs.rb
index cd6f7c6..2ccd78b 100644
--- a/lib/mogilefs/mogilefs.rb
+++ b/lib/mogilefs/mogilefs.rb
@@ -318,7 +318,7 @@ class MogileFS::MogileFS < MogileFS::Client
     opts[:fid] = res['fid']
     opts[:content_length] ||= bytes if bytes
     opts[:new_file_max_time] ||= @new_file_max_time
-    opts[:start_time] = Time.now
+    opts[:start_time] = MogileFS.now
     info = opts[:info] and info["class"] = klass || "default"
 
     case (dests[0][1] rescue nil)
diff --git a/lib/mogilefs/mysql.rb b/lib/mogilefs/mysql.rb
index 9d59a0a..e2a16e5 100644
--- a/lib/mogilefs/mysql.rb
+++ b/lib/mogilefs/mysql.rb
@@ -21,7 +21,7 @@ class MogileFS::Mysql
   def initialize(args = {})
     @my = args[:mysql]
     @query_method = @my.respond_to?(:c_async_query) ? :c_async_query : :query
-    @last_update_device = @last_update_domain = Time.at(0)
+    @last_update_device = @last_update_domain = 0
     @cache_domain = @cache_device = nil
   end
 
@@ -139,7 +139,9 @@ class MogileFS::Mysql
     }.freeze
 
     def refresh_device(force = false)
-      return @cache_device if ! force && ((Time.now - @last_update_device) < 60)
+      if ! force && ((MogileFS.now - @last_update_device) < 60)
+        return @cache_device
+      end
       tmp = {}
       res = query(GET_DEVICES)
       res.each do |devid, hostip, altip, http_port, http_get_port,
@@ -154,16 +156,18 @@ class MogileFS::Mysql
           :http_get_port => http_get_port ?  http_get_port.to_i : http_port,
         }.freeze
       end
-      @last_update_device = Time.now
+      @last_update_device = MogileFS.now
       @cache_device = tmp.freeze
     end
 
     def refresh_domain(force = false)
-      return @cache_domain if ! force && ((Time.now - @last_update_domain) < 5)
+      if ! force && ((MogileFS.now - @last_update_domain) < 5)
+        return @cache_domain
+      end
       tmp = {}
       res = query(GET_DOMAINS)
       res.each { |dmid,namespace| tmp[namespace] = dmid.to_i }
-      @last_update_domain = Time.now
+      @last_update_domain = MogileFS.now
       @cache_domain = tmp.freeze
     end
 
diff --git a/lib/mogilefs/new_file/common.rb b/lib/mogilefs/new_file/common.rb
index b901f67..c102901 100644
--- a/lib/mogilefs/new_file/common.rb
+++ b/lib/mogilefs/new_file/common.rb
@@ -20,7 +20,7 @@ module MogileFS::NewFile::Common
 
   def read_response(sock)
     tout = @opts[:new_file_max_time] || 3600.0
-    start_time = @opts[:start_time] and tout -= Time.now - start_time
+    start_time = @opts[:start_time] and tout -= MogileFS.now - start_time
     set_socket_options(sock)
     case line = sock.timed_read(23, "", tout > 0.0 ? tout : 0)
     when %r{^HTTP/\d\.\d\s+(2\d\d)\s} # success!