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
|