Ruby mogilefs-client dev/users discussion/patches/bugs/help/...
 help / color / Atom feed
* [PATCH] use monotonic clock if possible on Ruby 2.1+
@ 2015-05-27 22:02 Eric Wong
  0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2015-05-27 22:02 UTC (permalink / raw)
  To: mogilefs-client-public; +Cc: Eric Wong

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.
---
 lib/mogilefs.rb                 | 10 ++++++++++
 lib/mogilefs/backend.rb         | 14 +++++++-------
 lib/mogilefs/http_reader.rb     |  4 ++--
 lib/mogilefs/mogilefs.rb        |  2 +-
 lib/mogilefs/mysql.rb           | 14 +++++++++-----
 lib/mogilefs/new_file/common.rb |  2 +-
 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 @@ def dispatch_unlocked(request, timeout = @timeout) # :nodoc:
       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 @@ def pipeline_gets_unlocked(io, timeout) # :nodoc:
   end
 
   def timeout_update(timeout, t0) # :nodoc:
-    timeout -= (Time.now - t0)
+    timeout -= (MogileFS.now - t0)
     timeout < 0 ? 0 : timeout
   end
 
@@ -174,12 +174,12 @@ def timeout_update(timeout, t0) # :nodoc:
   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 @@ def pipeline_dispatch(cmd, args, &block) # :nodoc:
         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 @@ def socket
     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 @@ def self.first(paths, timeout, range = nil)
   # 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 @@ def new_file(key, args = nil, bytes = nil) # :yields: file
     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 @@ def query(sql)
     }.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 @@ def refresh_device(force = false)
           :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 @@ class NonRetryableError < MogileFS::Error; end
 
   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!
-- 
EW


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, back to index

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-27 22:02 [PATCH] use monotonic clock if possible on Ruby 2.1+ Eric Wong

Ruby mogilefs-client dev/users discussion/patches/bugs/help/...

Archives are clonable:
	git clone --mirror https://yhbt.net/mogilefs-client-public
	git clone --mirror http://ou63pmih66umazou.onion/mogilefs-client-public

Example config snippet for mirrors

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.file-systems.mogilefs.ruby
	nntp://ou63pmih66umazou.onion/inbox.comp.file-systems.mogilefs.ruby

 note: .onion URLs require Tor: https://www.torproject.org/

AGPL code for this site: git clone https://public-inbox.org/public-inbox.git