1 # -*- encoding: binary -*-
2 # internal implementation details here, do not rely on this in your code
5 module MogileFS::SocketCommon
6 attr_reader :mogilefs_addr
8 def post_init(host, port)
9 @mogilefs_addr = "#{host}:#{port}"
10 Socket.const_defined?(:TCP_NODELAY) and
11 setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
15 def unreadable_socket!(timeout)
16 raise MogileFS::UnreadableSocketError,
17 "#@mogilefs_addr never became readable (timeout=#{timeout.inspect})"
20 def request_truncated!(written, expect, timeout)
21 timeout = timeout.inspect
22 raise MogileFS::RequestTruncatedError,
23 "request truncated (sent #{written} expected #{expect} timeout=#{timeout})"
26 def timed_gets(timeout = 5)
27 unless defined?(@rbuf) && @rbuf
28 @rbuf = timed_read(1024, "", timeout) or return # EOF
31 @rbuf.sub!(/\A(.*\n)/, "".freeze) and return $1
33 if timed_read(1024, tmp, timeout)
36 # EOF, return the last buffered bit even without separatar matching
37 # (not ideal for MogileFS, this is an error)
38 return @rbuf.empty? ? nil : @rbuf.slice!(0, @rbuf.size)
43 def read(size, buf = "", timeout = 5)
44 timed_read(size, buf, timeout) or return # nil/EOF
46 while (remaining = size - buf.bytesize) > 0
48 timed_read(remaining, tmp, timeout) or return buf # truncated
55 def readpartial(size, buf = "", timeout = 5)
56 timed_read(size, buf, timeout) or raise EOFError, "end of file reached"
59 # Workaround for https://bugs.ruby-lang.org/issues/13085
60 # (excessive garbage from IO#write)
61 # This regression was introduced in Ruby 2.0 (r34847)
62 # and it is fixed in Ruby 2.4.1+
63 # backport request: https://bugs.ruby-lang.org/issues/13299
64 if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby' &&
68 # we expect 2.2.7 and 2.3.4 to not need this
71 '2.4.0' # 2.4.1 is good!
73 # Blocking TCP writes would error out long before one day,
74 # and MogileFS won't allow file creations which take over a day.
75 timed_write(buf, 86400)