mogilefs-client.git  about / heads / tags
MogileFS client library for Ruby
blob acbbacad7207e2ec992f383d84c16c29822ac3c8 3186 bytes (raw)
$ git show HEAD:lib/mogilefs/socket/pure_ruby.rb	# shows this blob on the CLI

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 
# -*- encoding: binary -*-
# internal implementation details here, do not rely on them in your code
require 'io/wait'

class MogileFS::Socket < Socket
  include MogileFS::SocketCommon

  if RUBY_VERSION.to_f >= 2.3
    def self.start(host, port)
      sock = new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
      sock.connect_nonblock(sockaddr_in(port, host), :exception => false)
      sock.post_init(host, port)
    end
  else
    def self.start(host, port)
      sock = new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
      begin
        sock.connect_nonblock(sockaddr_in(port, host))
      rescue Errno::EINPROGRESS
      end
      sock.post_init(host, port)
    end
  end

  def self.tcp(host, port, timeout = 5)
    sock = start(host, port)
    unless sock.wait_writable(timeout)
      sock.close
      raise MogileFS::Timeout, 'socket connect timeout'
    end
    sock
  end

  def wait_writable(timeout = nil)
    IO.select(nil, [ self ], nil, timeout)
  end unless self.instance_methods.include?(:wait_writable) # Ruby <2.0.0

  def timed_peek(len, dst, timeout = 5)
    begin
      rc = recv_nonblock(len, Socket::MSG_PEEK)
      return rc.empty? ? nil : dst.replace(rc)
    rescue Errno::EAGAIN
      wait(timeout) or unreadable_socket!(timeout)
    rescue EOFError
      dst.respond_to?(:clear) ? dst.clear : dst.replace("")
      return
    end while true
  rescue EOFError
    nil
  end

  # write_nonblock and read_nonblock support `exception: false`
  if RUBY_VERSION.to_f >= 2.1
    def timed_read(len, dst = "", timeout = 5)
      case rc = read_nonblock(len, dst, :exception => false)
      when String
        return rc
      when :wait_readable
        wait(timeout) or unreadable_socket!(timeout)
      when nil
        return
      end while true
    rescue EOFError
      nil
    end

    def timed_write(buf, timeout = 5)
      written = 0
      expect = buf.bytesize
      case rc = write_nonblock(buf, :exception => false)
      when Integer
        return expect if rc == buf.bytesize
        written += rc
        buf = buf.byteslice(rc, buf.bytesize) # Ruby 1.9.3+
      when :wait_writable
        wait_writable(timeout) or request_truncated!(written, expect, timeout)
      end while true
    end
  else # Ruby 1.8.7 - 2.0.0
    def timed_read(len, dst = "", timeout = 5)
      begin
        return read_nonblock(len, dst)
      rescue Errno::EAGAIN
        wait(timeout) or unreadable_socket!(timeout)
      rescue EOFError
        return
      end while true
    rescue EOFError
      nil
    end

    def timed_write(buf, timeout = 5)
      written = 0
      expect = buf.bytesize
      begin
        rc = write_nonblock(buf)
        return expect if rc == buf.bytesize
        written += rc

        if buf.respond_to?(:byteslice) # Ruby 1.9.3+
          buf = buf.byteslice(rc, buf.bytesize)
        else
          if buf.respond_to?(:encoding) && buf.encoding != Encoding::BINARY
            buf = buf.dup.force_encoding(Encoding::BINARY)
          end
          buf = buf.slice(rc, buf.bytesize)
        end
      rescue Errno::EAGAIN
        wait_writable(timeout) or request_truncated!(written, expect, timeout)
      end while true
    end
  end
end

git clone https://yhbt.net/mogilefs-client.git