3 require 'mogilefs/util'
5 module MogileFS::Network
6 # given an array of URIs, verify that at least one of them is accessible
7 # with the expected HTTP code within the timeout period (in seconds).
8 def verify_uris(uris = [], expect = '200', timeout = 2.00)
11 # first, we asynchronously connect to all of them
13 sock = Socket.mogilefs_new_nonblock(uri.host, uri.port) rescue next
17 # wait for at least one of them to finish connecting and send
18 # HTTP requests to the connected ones
19 sockets, timeout = get_writable_set(uri_socks, timeout)
21 # Await a response from the sockets we had written to, we only need one
22 # valid response, but we'll take more if they return simultaneously
23 sockets[0] ? get_readable_uris(sockets, uri_socks, expect, timeout) : []
26 uri_socks.keys.each { |sock| sock.close rescue nil }
30 include MogileFS::Util
32 # returns an array of writeable Sockets and leftover from timeout
33 def get_writable_set(uri_socks, timeout)
38 IO.select(nil, uri_socks.keys, nil, timeout > 0 ? timeout : 0)
40 # get rid of bad descriptors
41 uri_socks.delete_if do |sock, uri|
44 false # should never get here for HTTP, really...
45 rescue Errno::EAGAIN, Errno::EINTR
52 timeout -= (Time.now - t0)
56 break unless r && r[1]
60 # we don't care about short/interrupted writes here, if the
61 # following request fails or blocks then the server is
64 "HEAD #{uri_socks[sock].request_uri} HTTP/1.0\r\n\r\n")
71 timeout -= (Time.now - t0)
72 end until (sockets[0] || timeout < 0)
77 # returns an array of URIs from uri_socks that are good
78 def get_readable_uris(sockets, uri_socks, expect, timeout)
83 r = IO.select(sockets, nil, nil, timeout > 0 ? timeout : 0) rescue nil
85 (r && r[0] ? r[0] : sockets).each do |sock|
87 sock.recv_nonblock(128, Socket::MSG_PEEK)
88 rescue Errno::EAGAIN, Errno::EINTR
91 sockets.delete(sock) # socket went bad
95 if buf && /\AHTTP\/[\d\.]+ #{expect} / =~ buf
96 ok_uris << uri_socks.delete(sock)
100 timeout -= (Time.now - t0)
101 end until ok_uris[0] || timeout < 0
106 end # module MogileFS::Network