make http_read_sock and friends use new socket API
[ruby-mogilefs-client.git] / lib / mogilefs / socket_common.rb
blob567e715f40ffa7a946ed09b8ec4bb6e5ec58a2ae
1 # -*- encoding: binary -*-
2 require "socket"
4 module MogileFS::SocketCommon
5   attr_reader :mogilefs_addr
6   attr_accessor :mogilefs_size
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)
12     self
13   end
15   def unreadable_socket!
16     raise MogileFS::UnreadableSocketError,
17           "#@mogilefs_addr never became readable"
18   end
20   def request_truncated!(written, expect)
21     raise MogileFS::RequestTruncatedError,
22           "request truncated (sent #{written} expected #{expect})"
23   end
25   SEP_RE = /\A(.*?#{Regexp.escape("\n")})/
26   def timed_gets(timeout = 5)
27     unless defined?(@rbuf)
28       @rbuf = timed_read(1024, "", timeout) or return # EOF
29     end
30     begin
31       @rbuf.sub!(SEP_RE, "") and return $1
32       tmp ||= ""
33       if timed_read(1024, tmp, timeout)
34         @rbuf << tmp
35       else
36         # EOF, return the last buffered bit even without SEP_RE matching
37         # (not ideal for MogileFS, this is an error)
38         return @rbuf.empty? ? nil : @rbuf.slice!(0, @rbuf.size)
39       end
40     end while true
41   end
43   def read(size, buf = "", timeout = 5)
44     timed_read(size, buf, timeout) or return # nil/EOF
46     while size > buf.bytesize
47       tmp ||= ""
48       timed_read(size - buf.bytesize, tmp, timeout) or return buf # truncated
49       buf << tmp
50     end
52     buf # full read
53   end
54 end