diff options
author | Eric Wong <normalperson@yhbt.net> | 2011-12-07 02:03:05 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2011-12-07 02:29:23 +0000 |
commit | 0bbbd8cfa2df665bc22a47831adf91668e391e3e (patch) | |
tree | 08b1c1e8cfabaca403ae34bc2b68e4d8510d0610 | |
parent | da58f47f541cff65e814a614ecff722ba2a35bf8 (diff) | |
download | mogilefs-client-0bbbd8cfa2df665bc22a47831adf91668e391e3e.tar.gz |
TCP keepalives are inexpensive, so we can use them to monitor whether or not our connection is still alive while uploading. Remote servers make take an unpredictable amount of time to actually write out the data we've uploaded (and empty socket buffers to receive more), so it is extremely difficult to calculate an effective timeout for select() or poll().
-rw-r--r-- | lib/mogilefs/http_file.rb | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/lib/mogilefs/http_file.rb b/lib/mogilefs/http_file.rb index b8bfd48..0d6faf5 100644 --- a/lib/mogilefs/http_file.rb +++ b/lib/mogilefs/http_file.rb @@ -1,5 +1,6 @@ # -*- encoding: binary -*- # here are internal implementation details, do not use them in your code +require 'socket' require 'stringio' require 'uri' require 'digest/md5' @@ -106,7 +107,7 @@ class MogileFS::HTTPFile < StringIO # returns file size if the socket finished writing def upload(devid, uri) # :nodoc: sock = MogileFS::Socket.tcp(uri.host, uri.port) - sock.setsockopt(Socket::IPPROTO_TCP, Socket::SO_KEEPALIVE, 1) + set_socket_options(sock) file_size = length if @streaming_io @@ -192,4 +193,27 @@ class MogileFS::HTTPFile < StringIO commit super end + + # :stopdoc: + # aggressive keepalive settings on Linux + Ruby 1.9.2+ + TCP_KEEPALIVE = { + :TCP_KEEPIDLE => 60, # seconds time before keepalive packet is sent + :TCP_KEEPINTVL => 5, + :TCP_KEEPCNT => 2, # number of retries + } + + req_consts = TCP_KEEPALIVE.keys + if (Socket.constants & req_consts).size == req_consts.size + def set_socket_options(sock) + sock.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, 1) + TCP_KEEPALIVE.each do |k,v| + sock.setsockopt(:IPPROTO_TCP, k, v) + end + end + else + def set_socket_options(sock) + sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1) + end + end + # :startdoc: end |