Class: GorgonBunny::Socket
- Inherits:
-
TCPSocket
- Object
- TCPSocket
- GorgonBunny::Socket
- Defined in:
- lib/gorgon_bunny/lib/gorgon_bunny/socket.rb
Overview
TCP socket extension that uses TCP_NODELAY and supports reading fully.
Heavily inspired by Dalli by Mike Perham.
Constant Summary collapse
- READ_RETRY_EXCEPTION_CLASSES =
IO::WaitReadable is 1.9+ only
[Errno::EAGAIN, Errno::EWOULDBLOCK]
Instance Attribute Summary collapse
-
#options ⇒ Object
Returns the value of attribute options.
Class Method Summary collapse
Instance Method Summary collapse
-
#read_fully(count, timeout = nil) ⇒ String
Reads given number of bytes with an optional timeout.
-
#write_nonblock_fully(data) ⇒ Object
Writes provided data using IO#write_nonblock, taking care of handling of exceptions it raises when writing would fail (e.g. due to socket buffer being full).
Instance Attribute Details
#options ⇒ Object
Returns the value of attribute options.
10 11 12 |
# File 'lib/gorgon_bunny/lib/gorgon_bunny/socket.rb', line 10 def @options end |
Class Method Details
.open(host, port, options = {}) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/gorgon_bunny/lib/gorgon_bunny/socket.rb', line 16 def self.open(host, port, = {}) Timeout.timeout([:socket_timeout], ClientTimeout) do sock = new(host, port) if Socket.constants.include?('TCP_NODELAY') || Socket.constants.include?(:TCP_NODELAY) sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true) end sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if .fetch(:keepalive, true) sock. = {:host => host, :port => port}.merge() sock end end |
Instance Method Details
#read_fully(count, timeout = nil) ⇒ String
Reads given number of bytes with an optional timeout
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/gorgon_bunny/lib/gorgon_bunny/socket.rb', line 35 def read_fully(count, timeout = nil) return nil if @__bunny_socket_eof_flag__ value = '' begin loop do value << read_nonblock(count - value.bytesize) break if value.bytesize >= count end rescue EOFError # @eof will break Rubinius' TCPSocket implementation. MK. @__bunny_socket_eof_flag__ = true rescue *READ_RETRY_EXCEPTION_CLASSES if IO.select([self], nil, nil, timeout) retry else raise Timeout::Error, "IO timeout when reading #{count} bytes" end end value end |
#write_nonblock_fully(data) ⇒ Object
Writes provided data using IO#write_nonblock, taking care of handling of exceptions it raises when writing would fail (e.g. due to socket buffer being full).
IMPORTANT: this method will mutate (slice) the argument. Pass in duplicates if this is not appropriate in your case.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/gorgon_bunny/lib/gorgon_bunny/socket.rb', line 67 def write_nonblock_fully(data) return nil if @__bunny_socket_eof_flag__ begin while !data.empty? written = self.write_nonblock(data) data.slice!(0, written) end rescue Errno::EWOULDBLOCK, Errno::EAGAIN IO.select([], [self]) retry end data.bytesize end |