new MogileFS::Network module, move verify_uris there
[ruby-mogilefs-client.git] / lib / mogilefs / network.rb
bloba3c3bd3020108408139fa2497d2047d3b04f0eb9
1 require 'mogilefs'
2 require 'socket'
4 module MogileFS::Network
5   # given an array of URIs, verify that at least one of them is accessible
6   # with the expected HTTP code within the timeout period (in seconds).
7   def verify_uris(uris = [], expect = '200', timeout = 2.00)
8     uri_socks = {}
9     ok_uris = []
10     sockets = []
12     # first, we asynchronously connect to all of them
13     uris.each do |uri|
14       sock = Socket.mogilefs_new_nonblock(uri.host, uri.port) rescue next
15       uri_socks[sock] = uri
16     end
18     # wait for at least one of them to finish connecting and send
19     # HTTP requests to the connected ones
20     begin
21       t0 = Time.now
22       r = IO.select(nil, uri_socks.keys, nil, timeout > 0 ? timeout : 0)
23       timeout -= (Time.now - t0)
24       break unless r && r[1]
25       r[1].each do |sock|
26         begin
27           sock.syswrite "HEAD #{uri_socks[sock].request_uri} HTTP/1.0\r\n\r\n"
28           sockets << sock
29         rescue
30           sock.close rescue nil
31         end
32       end
33     end until sockets[0] || timeout < 0
35     # Await a response from the sockets we had written to, we only need one
36     # valid response, but we'll take more if they return simultaneously
37     if sockets[0]
38       begin
39         t0 = Time.now
40         r = IO.select(sockets, nil, nil, timeout > 0 ? timeout : 0)
41         timeout -= (Time.now - t0)
42         break unless r && r[0]
43         r[0].each do |sock|
44           buf = sock.recv_nonblock(128, Socket::MSG_PEEK) rescue next
45           if buf && /\AHTTP\/[\d\.]+ #{expect} / =~ buf
46             ok_uris << uri_socks.delete(sock)
47             sock.close rescue nil
48           end
49         end
50       end
51     end until ok_uris[0] || timeout < 0
53     ok_uris
54     ensure
55       uri_socks.keys.each { |sock| sock.close rescue nil }
56   end
58 end # module MogileFS::Network