1 # -*- encoding: binary -*-
2 # here are internal implementation details, do not use them in your code
5 require 'mogilefs/util'
7 module MogileFS::Network
8 # given an array of URIs, verify that at least one of them is accessible
9 # with the expected HTTP code within the timeout period (in seconds).
10 def verify_uris(uris = [], expect = '200', timeout = 2.00)
13 # first, we asynchronously connect to all of them
15 sock = MogileFS::Socket.start(uri.host, uri.port) rescue next
19 # wait for at least one of them to finish connecting and send
20 # HTTP requests to the connected ones
21 sockets, timeout = get_writable_set(uri_socks, timeout)
23 # Await a response from the sockets we had written to, we only need one
24 # valid response, but we'll take more if they return simultaneously
25 sockets[0] ? get_readable_uris(sockets, uri_socks, expect, timeout) : []
28 uri_socks.keys.each { |sock| sock.close rescue nil }
32 include MogileFS::Util
34 # returns an array of writeable Sockets and leftover from timeout
35 def get_writable_set(uri_socks, timeout)
40 IO.select(nil, uri_socks.keys, nil, timeout > 0 ? timeout : 0)
42 # get rid of bad descriptors
43 uri_socks.delete_if do |sock, uri|
46 false # should never get here for HTTP, really...
47 rescue Errno::EAGAIN, Errno::EINTR
54 timeout -= (Time.now - t0)
58 break unless r && r[1]
62 # we don't care about short/interrupted writes here, if the
63 # following request fails or blocks then the server is
66 "HEAD #{uri_socks[sock].request_uri} HTTP/1.0\r\n\r\n")
73 timeout -= (Time.now - t0)
74 end until (sockets[0] || timeout < 0)
79 # returns an array of URIs from uri_socks that are good
80 def get_readable_uris(sockets, uri_socks, expect, timeout)
85 r = IO.select(sockets, nil, nil, timeout > 0 ? timeout : 0) rescue nil
87 (r && r[0] ? r[0] : sockets).each do |sock|
89 sock.recv_nonblock(128, Socket::MSG_PEEK)
90 rescue Errno::EAGAIN, Errno::EINTR
93 sockets.delete(sock) # socket went bad
97 if buf && /\AHTTP\/[\d\.]+ #{expect} / =~ buf
98 ok_uris << uri_socks.delete(sock)
102 timeout -= (Time.now - t0)
103 end until ok_uris[0] || timeout < 0
108 end # module MogileFS::Network