From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-2.9 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00 shortcircuit=no autolearn=unavailable version=3.3.2 X-Original-To: mogilefs-client-public@bogomips.org Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 4B2D11F52D; Wed, 27 May 2015 22:02:55 +0000 (UTC) From: Eric Wong To: mogilefs-client-public@bogomips.org Cc: Eric Wong Subject: [PATCH] use monotonic clock if possible on Ruby 2.1+ Date: Wed, 27 May 2015 22:02:55 +0000 Message-Id: <1432764175-15121-1-git-send-email-e@80x24.org> List-Id: 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