mogilefs-client 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,2 +1,4 @@
1
1
  /pkg
2
2
  /doc
3
+ /.config
4
+ /InstalledFiles
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ = 2.0.1
2
+ * verify_uris method made more robust
3
+ * preliminary Ruby 1.9 compatibility, tests still need some work
4
+ * allow store_content to be used with a streamable object of known length
5
+ * add setup.rb for non-RubyGems users
6
+
1
7
  = 2.0.0
2
8
 
3
9
  * use a set of standard exceptions based on MogileFS::Error,
data/README.txt CHANGED
@@ -60,7 +60,7 @@ Then install the gem:
60
60
 
61
61
  # Store the contents of 'image.jpeg' into the key 'my_image' with a class of
62
62
  # 'image' using an open IO.
63
- File.open 'image.jpeg' do |fp|
63
+ File.open 'image.jpeg', 'rb' do |fp|
64
64
  mg.store_file 'my_image', 'image', fp
65
65
  end
66
66
 
data/bin/mog CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'mogilefs'
3
3
  require 'optparse'
4
+ [ STDIN, STDOUT, STDERR].each { |io| io.binmode }
4
5
 
5
6
  trap('INT') { exit 130 }
6
7
  trap('PIPE') { exit 0 }
data/lib/mogilefs.rb CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  module MogileFS
8
8
 
9
- VERSION = '2.0.0'.freeze
9
+ VERSION = '2.0.1'.freeze
10
10
 
11
11
  ##
12
12
  # Raised when a socket remains unreadable for too long.
@@ -274,9 +274,14 @@ class MogileFS::Backend
274
274
 
275
275
  ##
276
276
  # Escapes naughty URL characters.
277
-
278
- def url_escape(str)
279
- str.gsub(/([^\w\,\-.\/\\\: ])/) { "%%%02x" % $1[0] }.tr(' ', '+')
277
+ if ''.respond_to?(:ord) # Ruby 1.9
278
+ def url_escape(str)
279
+ str.gsub(/([^\w\,\-.\/\\\: ])/) { "%%%02x" % $1.ord }.tr(' ', '+')
280
+ end
281
+ else # Ruby 1.8
282
+ def url_escape(str)
283
+ str.gsub(/([^\w\,\-.\/\\\: ])/) { "%%%02x" % $1[0] }.tr(' ', '+')
284
+ end
280
285
  end
281
286
 
282
287
  ##
@@ -44,12 +44,15 @@ class MogileFS::HTTPFile < StringIO
44
44
 
45
45
  attr_accessor :big_io
46
46
 
47
+ attr_accessor :streaming_io
48
+
47
49
  ##
48
50
  # Works like File.open. Use MogileFS::MogileFS#new_file instead of this
49
51
  # method.
50
52
 
51
53
  def self.open(*args)
52
54
  fp = new(*args)
55
+ fp.set_encoding(Encoding::BINARY) if fp.respond_to?(:set_encoding)
53
56
 
54
57
  return fp unless block_given?
55
58
 
@@ -72,6 +75,7 @@ class MogileFS::HTTPFile < StringIO
72
75
  @klass = klass
73
76
  @key = key
74
77
  @big_io = nil
78
+ @streaming_io = nil
75
79
 
76
80
  @dests = dests
77
81
  @tried = {}
@@ -87,9 +91,16 @@ class MogileFS::HTTPFile < StringIO
87
91
  sock = Socket.mogilefs_new(uri.host, uri.port)
88
92
  sock.mogilefs_tcp_cork = true
89
93
 
90
- if @big_io
94
+ if @streaming_io
95
+ file_size = @streaming_io.length
96
+ syswrite_full(sock, "PUT #{uri.request_uri} HTTP/1.0\r\n" \
97
+ "Content-Length: #{file_size}\r\n\r\n")
98
+ @streaming_io.call(Proc.new do |data_to_write|
99
+ syswrite_full(sock, data_to_write)
100
+ end)
101
+ elsif @big_io
91
102
  # Don't try to run out of memory
92
- File.open(@big_io) do |fp|
103
+ File.open(@big_io, "rb") do |fp|
93
104
  file_size = fp.stat.size
94
105
  fp.sync = true
95
106
  syswrite_full(sock, "PUT #{uri.request_uri} HTTP/1.0\r\n" \
@@ -148,7 +148,7 @@ class MogileFS::MogileFS < MogileFS::Client
148
148
  mfp.big_io = file
149
149
  return
150
150
  else
151
- return File.open(file) { |fp| sysrwloop(fp, mfp) }
151
+ return File.open(file, "rb") { |fp| sysrwloop(fp, mfp) }
152
152
  end
153
153
  end
154
154
  end
@@ -161,7 +161,11 @@ class MogileFS::MogileFS < MogileFS::Client
161
161
  raise MogileFS::ReadOnlyError if readonly?
162
162
 
163
163
  new_file key, klass do |mfp|
164
- mfp << content
164
+ if content.is_a?(MogileFS::Util::StoreContent)
165
+ mfp.streaming_io = content
166
+ else
167
+ mfp << content
168
+ end
165
169
  end
166
170
 
167
171
  content.length
@@ -7,8 +7,6 @@ module MogileFS::Network
7
7
  # with the expected HTTP code within the timeout period (in seconds).
8
8
  def verify_uris(uris = [], expect = '200', timeout = 2.00)
9
9
  uri_socks = {}
10
- ok_uris = []
11
- sockets = []
12
10
 
13
11
  # first, we asynchronously connect to all of them
14
12
  uris.each do |uri|
@@ -18,47 +16,89 @@ module MogileFS::Network
18
16
 
19
17
  # wait for at least one of them to finish connecting and send
20
18
  # HTTP requests to the connected ones
21
- begin
22
- t0 = Time.now
23
- r = IO.select(nil, uri_socks.keys, nil, timeout > 0 ? timeout : 0)
24
- timeout -= (Time.now - t0)
25
- break unless r && r[1]
26
- r[1].each do |sock|
27
- begin
28
- # we don't about short/interrupted writes here, if the following
29
- # request fails or blocks then the server is flat-out hopeless
30
- sock.syswrite "HEAD #{uri_socks[sock].request_uri} HTTP/1.0\r\n\r\n"
31
- sockets << sock
32
- rescue
33
- sock.close rescue nil
34
- end
35
- end
36
- end until sockets[0] || timeout < 0
19
+ sockets, timeout = get_writable_set(uri_socks, timeout)
37
20
 
38
21
  # Await a response from the sockets we had written to, we only need one
39
22
  # valid response, but we'll take more if they return simultaneously
40
- if sockets[0]
23
+ sockets[0] ? get_readable_uris(sockets, uri_socks, expect, timeout) : []
24
+
25
+ ensure
26
+ uri_socks.keys.each { |sock| sock.close rescue nil }
27
+ end
28
+
29
+ private
30
+ include MogileFS::Util
31
+
32
+ # returns an array of writeable Sockets and leftover from timeout
33
+ def get_writable_set(uri_socks, timeout)
34
+ sockets = []
41
35
  begin
42
36
  t0 = Time.now
43
- r = IO.select(sockets, nil, nil, timeout > 0 ? timeout : 0)
37
+ r = begin
38
+ IO.select(nil, uri_socks.keys, nil, timeout > 0 ? timeout : 0)
39
+ rescue
40
+ # get rid of bad descriptors
41
+ uri_socks.delete_if do |sock, uri|
42
+ begin
43
+ sock.recv_nonblock(1)
44
+ false # should never get here for HTTP, really...
45
+ rescue Errno::EAGAIN, Errno::EINTR
46
+ false
47
+ rescue
48
+ sock.close rescue nil
49
+ true
50
+ end
51
+ end
52
+ timeout -= (Time.now - t0)
53
+ retry if timeout >= 0
54
+ end
55
+
56
+ break unless r && r[1]
57
+
58
+ r[1].each do |sock|
59
+ begin
60
+ # we don't about short/interrupted writes here, if the following
61
+ # request fails or blocks then the server is flat-out hopeless
62
+ sock.syswrite "HEAD #{uri_socks[sock].request_uri} HTTP/1.0\r\n\r\n"
63
+ sockets << sock
64
+ rescue
65
+ sock.close rescue nil
66
+ end
67
+ end
68
+
44
69
  timeout -= (Time.now - t0)
45
- break unless r && r[0]
46
- r[0].each do |sock|
47
- buf = sock.recv_nonblock(128, Socket::MSG_PEEK) rescue next
70
+ end until (sockets[0] || timeout < 0)
71
+
72
+ [ sockets, timeout ]
73
+ end
74
+
75
+ # returns an array of URIs from uri_socks that are good
76
+ def get_readable_uris(sockets, uri_socks, expect, timeout)
77
+ ok_uris = []
78
+
79
+ begin
80
+ t0 = Time.now
81
+ r = IO.select(sockets, nil, nil, timeout > 0 ? timeout : 0) rescue nil
82
+
83
+ (r && r[0] ? r[0] : sockets).each do |sock|
84
+ buf = begin
85
+ sock.recv_nonblock(128, Socket::MSG_PEEK)
86
+ rescue Errno::EAGAIN, Errno::EINTR
87
+ next
88
+ rescue
89
+ sockets.delete(sock) # socket went bad
90
+ next
91
+ end
92
+
48
93
  if buf && /\AHTTP\/[\d\.]+ #{expect} / =~ buf
49
94
  ok_uris << uri_socks.delete(sock)
50
95
  sock.close rescue nil
51
96
  end
52
97
  end
53
- end
54
- end until ok_uris[0] || timeout < 0
55
-
56
- ok_uris
57
- ensure
58
- uri_socks.keys.each { |sock| sock.close rescue nil }
59
- end
98
+ timeout -= (Time.now - t0)
99
+ end until ok_uris[0] || timeout < 0
60
100
 
61
- private
62
- include MogileFS::Util
101
+ ok_uris
102
+ end
63
103
 
64
104
  end # module MogileFS::Network
data/lib/mogilefs/pool.rb CHANGED
@@ -31,8 +31,10 @@ class MogileFS::Pool
31
31
  def use
32
32
  object = get
33
33
  yield object
34
+ nil
34
35
  ensure
35
36
  put object
37
+ nil
36
38
  end
37
39
 
38
40
  def purge
data/lib/mogilefs/util.rb CHANGED
@@ -67,6 +67,16 @@ module MogileFS::Util
67
67
  # should never get here
68
68
  end
69
69
 
70
+ class StoreContent < Proc
71
+ def initialize(total_size, &writer_proc)
72
+ @total_size = total_size
73
+ super(&writer_proc)
74
+ end
75
+ def length
76
+ @total_size
77
+ end
78
+ end
79
+
70
80
  end
71
81
 
72
82
  require 'timeout'
data/test/setup.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  STDIN.sync = STDOUT.sync = STDERR.sync = true
2
2
  require 'test/unit'
3
-
3
+ require 'tempfile'
4
4
  require 'fileutils'
5
5
  require 'tmpdir'
6
6
  require 'stringio'
7
7
 
8
+ trap('CHLD') { Process.waitpid(-1, Process::WNOHANG) rescue nil }
9
+
8
10
  $TESTING = true
9
11
 
10
12
  require 'mogilefs'
@@ -52,37 +54,41 @@ end
52
54
 
53
55
  require 'socket'
54
56
  class TempServer
55
- attr_reader :port
57
+ attr_reader :port, :pid
56
58
 
57
59
  def self.destroy_all!
58
60
  ObjectSpace.each_object(TempServer) { |t| t.destroy! }
59
61
  end
60
62
 
61
- def initialize(server_proc)
62
- @thr = @port = @sock = nil
63
+ at_exit { TempServer.destroy_all! }
64
+
65
+ def initialize(server_proc, port = nil)
66
+ @pid = @sock = nil
67
+ @port = port
63
68
  retries = 0
64
69
  begin
65
- @port = 1024 + rand(32768 - 1024)
70
+ @port ||= 1024 + rand(32768 - 1024)
66
71
  @sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
67
- @sock.bind(Socket.pack_sockaddr_in(@port, '127.0.0.1'))
72
+ @sock.bind(Socket.pack_sockaddr_in(@port.to_i, '127.0.0.1'))
68
73
  @sock.listen(5)
69
74
  rescue Errno::EADDRINUSE, Errno::EACCES
70
75
  @sock.close rescue nil
71
76
  retry if (retries += 1) < 10
72
77
  end
73
- @thr = Thread.new(@sock, @port) { |s,p| server_proc.call(s, p) }
78
+ @pid = fork { server_proc.call(@sock, @port) }
79
+ @sock.close rescue nil
74
80
  end
75
81
 
76
82
  def destroy!
77
83
  @sock.close rescue nil
78
- Thread.kill(@thr) rescue nil
84
+ Process.kill('KILL', @pid) rescue nil
79
85
  end
80
86
 
81
87
  end
82
88
 
83
89
  class TestMogileFS < Test::Unit::TestCase
84
90
 
85
- undef_method :default_test
91
+ undef_method :default_test if method_defined?(:default_test)
86
92
 
87
93
  def setup
88
94
  @client = @klass.new :hosts => ['kaa:6001'], :domain => 'test'
data/test/test_backend.rb CHANGED
@@ -35,19 +35,20 @@ class TestBackend < Test::Unit::TestCase
35
35
  end
36
36
 
37
37
  def test_do_request
38
- received = ''
38
+ received = Tempfile.new('received')
39
39
  tmp = TempServer.new(Proc.new do |serv, port|
40
40
  client, client_addr = serv.accept
41
41
  client.sync = true
42
- received = client.recv 4096
42
+ received.syswrite(client.recv(4096))
43
43
  client.send "OK 1 you=win\r\n", 0
44
44
  end)
45
45
 
46
- @backend.hosts = "127.0.0.1:#{tmp.port}"
46
+ @backend.hosts = [ "127.0.0.1:#{tmp.port}" ]
47
47
 
48
48
  assert_equal({'you' => 'win'},
49
49
  @backend.do_request('go!', { 'fight' => 'team fight!' }))
50
- assert_equal "go! fight=team+fight%21\r\n", received
50
+ received.sysseek(0)
51
+ assert_equal "go! fight=team+fight%21\r\n", received.sysread(4096)
51
52
  ensure
52
53
  TempServer.destroy_all!
53
54
  end
@@ -118,24 +119,24 @@ class TestBackend < Test::Unit::TestCase
118
119
  end
119
120
 
120
121
  def test_readable_eh_readable
121
- accept_nr = 0
122
+ accept = Tempfile.new('accept')
122
123
  tmp = TempServer.new(Proc.new do |serv, port|
123
124
  client, client_addr = serv.accept
124
125
  client.sync = true
125
- accept_nr += 1
126
+ accept.syswrite('.')
126
127
  client.send('.', 0)
127
128
  sleep
128
129
  end)
129
130
 
130
131
  @backend = MogileFS::Backend.new :hosts => [ "127.0.0.1:#{tmp.port}" ]
131
132
  assert_equal true, @backend.readable?
132
- assert_equal 1, accept_nr
133
+ assert_equal 1, accept.stat.size
133
134
  ensure
134
135
  TempServer.destroy_all!
135
136
  end
136
137
 
137
138
  def test_readable_eh_not_readable
138
- tmp = TempServer.new(Proc.new { |a,b| sleep })
139
+ tmp = TempServer.new(Proc.new { |serv,port| serv.accept; sleep })
139
140
  @backend = MogileFS::Backend.new(:hosts => [ "127.0.0.1:#{tmp.port}" ],
140
141
  :timeout => 0.5)
141
142
  begin
@@ -158,36 +159,45 @@ class TestBackend < Test::Unit::TestCase
158
159
  end
159
160
 
160
161
  def test_socket_robust
161
- bad_accept_nr = accept_nr = 0
162
- queue = Queue.new
163
- bad = Proc.new { |serv,port| sleep; bad_accept_nr += 1 }
162
+ bad_accept = Tempfile.new('bad_accept')
163
+ accept = Tempfile.new('accept')
164
+ bad = Proc.new do |serv,port|
165
+ client, client_addr = serv.accept
166
+ bad_accept.syswrite('!')
167
+ end
164
168
  good = Proc.new do |serv,port|
165
169
  client, client_addr = serv.accept
166
- client.sync = true
167
- accept_nr += 1
168
- client.send '.', 0
169
- client.flush
170
- queue.push true
170
+ accept.syswrite('.')
171
+ client.syswrite('.')
172
+ client.close
171
173
  sleep
172
174
  end
173
175
  nr = 10
174
176
 
175
177
  nr.times do
176
178
  begin
177
- t1 = TempServer.new(bad)
179
+ t1 = TempServer.new(bad, ENV['TEST_DEAD_PORT'])
178
180
  t2 = TempServer.new(good)
179
- hosts = ["0:#{t1.port}", "0:#{t2.port}"]
180
- @backend = MogileFS::Backend.new(:hosts => hosts)
181
+ hosts = ["127.0.0.1:#{t1.port}", "127.0.0.1:#{t2.port}"]
182
+ @backend = MogileFS::Backend.new(:hosts => hosts.dup)
181
183
  assert_equal({}, @backend.dead)
184
+ old_chld_handler = trap('CHLD', 'DEFAULT')
182
185
  t1.destroy!
183
- @backend.socket
184
- wait = queue.pop
186
+ Process.waitpid(t1.pid)
187
+ trap('CHLD', old_chld_handler)
188
+ sock = @backend.socket
189
+ assert_equal Socket, sock.class
190
+ port = Socket.unpack_sockaddr_in(sock.getpeername).first
191
+ # p [ 'ports', "port=#{port}", "t1=#{t1.port}", "t2=#{t2.port}" ]
192
+ assert_equal t2.port, port
193
+ IO.select([sock])
194
+ assert_equal '.', sock.sysread(1)
185
195
  ensure
186
196
  TempServer.destroy_all!
187
197
  end
188
198
  end # nr.times
189
- assert_equal 0, bad_accept_nr
190
- assert_equal nr, accept_nr
199
+ assert_equal 0, bad_accept.stat.size
200
+ assert_equal nr, accept.stat.size
191
201
  end
192
202
 
193
203
  def test_shutdown
@@ -195,15 +205,18 @@ class TestBackend < Test::Unit::TestCase
195
205
  tmp = TempServer.new(Proc.new do |serv,port|
196
206
  client, client_addr = serv.accept
197
207
  accept_nr += 1
208
+ r = IO.select([client], [client])
209
+ client.syswrite(accept_nr.to_s)
198
210
  sleep
199
211
  end)
200
212
  @backend = MogileFS::Backend.new :hosts => [ "127.0.0.1:#{tmp.port}" ]
201
213
  assert @backend.socket
202
214
  assert ! @backend.socket.closed?
215
+ IO.select([@backend.socket])
216
+ resp = @backend.socket.sysread(4096)
203
217
  @backend.shutdown
204
218
  assert_equal nil, @backend.instance_variable_get(:@socket)
205
- assert_equal 1, accept_nr
206
-
219
+ assert_equal 1, resp.to_i
207
220
  ensure
208
221
  TempServer.destroy_all!
209
222
  end
@@ -20,15 +20,16 @@ class TestMogileFS__MogileFS < TestMogileFS
20
20
  end
21
21
 
22
22
  def test_get_file_data_http
23
- accept_nr = 0
23
+ tmp = Tempfile.new('accept')
24
+ accept = File.open(tmp.path, "ab")
24
25
  svr = Proc.new do |serv, port|
25
26
  client, client_addr = serv.accept
26
27
  client.sync = true
27
28
  readed = client.recv(4096, 0)
28
29
  assert(readed =~ \
29
30
  %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
31
+ accept.syswrite('.')
30
32
  client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\ndata!", 0)
31
- accept_nr += 1
32
33
  client.close
33
34
  end
34
35
  t1 = TempServer.new(svr)
@@ -39,13 +40,14 @@ class TestMogileFS__MogileFS < TestMogileFS
39
40
  @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
40
41
 
41
42
  assert_equal 'data!', @client.get_file_data('key')
42
- assert_equal 1, accept_nr
43
+ assert_equal 1, accept.stat.size
43
44
  ensure
44
45
  TempServer.destroy_all!
45
46
  end
46
47
 
47
48
  def test_get_file_data_http_not_found_failover
48
- accept_nr = 0
49
+ tmp = Tempfile.new('accept')
50
+ accept = File.open(tmp.path, 'ab')
49
51
  svr1 = Proc.new do |serv, port|
50
52
  client, client_addr = serv.accept
51
53
  client.sync = true
@@ -53,7 +55,7 @@ class TestMogileFS__MogileFS < TestMogileFS
53
55
  assert(readed =~ \
54
56
  %r{\AGET /dev1/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
55
57
  client.send("HTTP/1.0 404 Not Found\r\n\r\ndata!", 0)
56
- accept_nr += 1
58
+ accept.syswrite('.')
57
59
  client.close
58
60
  end
59
61
 
@@ -64,7 +66,7 @@ class TestMogileFS__MogileFS < TestMogileFS
64
66
  assert(readed =~ \
65
67
  %r{\AGET /dev2/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
66
68
  client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\ndata!", 0)
67
- accept_nr += 1
69
+ accept.syswrite('.')
68
70
  client.close
69
71
  end
70
72
 
@@ -75,7 +77,7 @@ class TestMogileFS__MogileFS < TestMogileFS
75
77
  @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
76
78
 
77
79
  assert_equal 'data!', @client.get_file_data('key')
78
- assert_equal 2, accept_nr
80
+ assert_equal 2, accept.stat.size
79
81
  ensure
80
82
  TempServer.destroy_all!
81
83
  end
@@ -92,16 +94,17 @@ class TestMogileFS__MogileFS < TestMogileFS
92
94
  assert_equal expect_size + header.size, File.size(tmpfp.path)
93
95
  tmpfp.sysseek(0)
94
96
 
95
- accept_nr = 0
97
+ accept = Tempfile.new('accept')
96
98
  svr = Proc.new do |serv, port|
97
99
  client, client_addr = serv.accept
98
100
  client.sync = true
99
- accept_nr += 1
101
+ accept.syswrite('.')
100
102
  readed = client.recv(4096, 0)
101
103
  assert(readed =~ \
102
104
  %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
103
105
  sysrwloop(tmpfp, client)
104
106
  client.close
107
+ exit 0
105
108
  end
106
109
  t1 = TempServer.new(svr)
107
110
  t2 = TempServer.new(svr)
@@ -120,13 +123,15 @@ class TestMogileFS__MogileFS < TestMogileFS
120
123
  read_nr = buf.size
121
124
  nr += read_nr
122
125
  assert_equal read_nr, data.syswrite(buf), "partial write"
126
+ rescue Errno::EAGAIN
127
+ retry
123
128
  rescue EOFError
124
129
  break
125
130
  end
126
131
  end
127
132
  end
128
133
  assert_equal expect_size, nr, "size mismatch"
129
- assert_equal 1, accept_nr
134
+ assert_equal 1, accept.stat.size
130
135
  end
131
136
 
132
137
  def test_get_paths
@@ -241,14 +246,14 @@ class TestMogileFS__MogileFS < TestMogileFS
241
246
  end
242
247
 
243
248
  def test_size_http
244
- accept_nr = 0
249
+ accept = Tempfile.new('accept')
245
250
  t = TempServer.new(Proc.new do |serv,port|
246
251
  client, client_addr = serv.accept
247
252
  client.sync = true
248
253
  readed = client.recv(4096, 0) rescue nil
254
+ accept.syswrite('.')
249
255
  assert_equal "HEAD /path HTTP/1.0\r\n\r\n", readed
250
256
  client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\n", 0)
251
- accept_nr += 1
252
257
  client.close
253
258
  end)
254
259
 
@@ -256,18 +261,18 @@ class TestMogileFS__MogileFS < TestMogileFS
256
261
  @backend.get_paths = { 'paths' => 1, 'path1' => path }
257
262
 
258
263
  assert_equal 5, @client.size('key')
259
- assert_equal 1, accept_nr
264
+ assert_equal 1, accept.stat.size
260
265
  end
261
266
 
262
267
  def test_bad_size_http
263
- accept_nr = 0
268
+ tmp = Tempfile.new('accept')
264
269
  t = TempServer.new(Proc.new do |serv,port|
265
270
  client, client_addr = serv.accept
266
271
  client.sync = true
267
272
  readed = client.recv(4096, 0) rescue nil
268
273
  assert_equal "HEAD /path HTTP/1.0\r\n\r\n", readed
269
274
  client.send("HTTP/1.0 404 Not Found\r\nContent-Length: 5\r\n\r\n", 0)
270
- accept_nr += 1
275
+ tmp.syswrite('.')
271
276
  client.close
272
277
  end)
273
278
 
@@ -275,17 +280,17 @@ class TestMogileFS__MogileFS < TestMogileFS
275
280
  @backend.get_paths = { 'paths' => 1, 'path1' => path }
276
281
 
277
282
  assert_nil @client.size('key')
278
- assert_equal 1, accept_nr
283
+ assert_equal 1, tmp.stat.size
279
284
  end
280
285
 
281
286
  def test_store_content_http
282
- received = ''
287
+ received = Tempfile.new('recieved')
283
288
  expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
284
289
 
285
290
  t = TempServer.new(Proc.new do |serv, accept|
286
291
  client, client_addr = serv.accept
287
292
  client.sync = true
288
- received = client.recv(4096, 0)
293
+ received.syswrite(client.recv(4096, 0))
289
294
  client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
290
295
  client.close
291
296
  end)
@@ -297,19 +302,61 @@ class TestMogileFS__MogileFS < TestMogileFS
297
302
 
298
303
  @client.store_content 'new_key', 'test', 'data'
299
304
 
300
- assert_equal expected, received
305
+ received.sysseek(0)
306
+ assert_equal expected, received.sysread(4096)
307
+ ensure
308
+ TempServer.destroy_all!
309
+ end
310
+
311
+
312
+ def test_store_content_with_writer_callback
313
+ received = Tempfile.new('recieved')
314
+ expected = "PUT /path HTTP/1.0\r\nContent-Length: 40\r\n\r\n"
315
+ 10.times do
316
+ expected += "data"
317
+ end
318
+ t = TempServer.new(Proc.new do |serv, accept|
319
+ client, client_addr = serv.accept
320
+ client.sync = true
321
+ nr = 0
322
+ loop do
323
+ buf = client.readpartial(8192) or break
324
+ break if buf.length == 0
325
+ assert_equal buf.length, received.syswrite(buf)
326
+ nr += buf.length
327
+ break if nr >= expected.size
328
+ end
329
+ client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
330
+ client.close
331
+ end)
332
+
333
+ @backend.create_open = {
334
+ 'devid' => '1',
335
+ 'path' => "http://127.0.0.1:#{t.port}/path",
336
+ }
337
+
338
+ cbk = MogileFS::Util::StoreContent.new(40) do |write_callback|
339
+ 10.times do
340
+ write_callback.call("data")
341
+ end
342
+ end
343
+ @client.store_content('new_key', 'test', cbk)
344
+
345
+ received.sysseek(0)
346
+ assert_equal expected, received.sysread(4096)
301
347
  ensure
302
348
  TempServer.destroy_all!
303
349
  end
304
350
 
305
351
  def test_store_content_multi_dest_failover
306
- received1 = received2 = nil
352
+ received1 = Tempfile.new('received')
353
+ received2 = Tempfile.new('received')
307
354
  expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
308
355
 
309
356
  t1 = TempServer.new(Proc.new do |serv, accept|
310
357
  client, client_addr = serv.accept
311
358
  client.sync = true
312
- received1 = client.recv(4096, 0)
359
+ received1.syswrite(client.recv(4096, 0))
313
360
  client.send("HTTP/1.0 500 Internal Server Error\r\n\r\n", 0)
314
361
  client.close
315
362
  end)
@@ -317,7 +364,7 @@ class TestMogileFS__MogileFS < TestMogileFS
317
364
  t2 = TempServer.new(Proc.new do |serv, accept|
318
365
  client, client_addr = serv.accept
319
366
  client.sync = true
320
- received2 = client.recv(4096, 0)
367
+ received2.syswrite(client.recv(4096, 0))
321
368
  client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
322
369
  client.close
323
370
  end)
@@ -331,8 +378,10 @@ class TestMogileFS__MogileFS < TestMogileFS
331
378
  }
332
379
 
333
380
  @client.store_content 'new_key', 'test', 'data'
334
- assert_equal expected, received1
335
- assert_equal expected, received2
381
+ received1.sysseek(0)
382
+ received2.sysseek(0)
383
+ assert_equal expected, received1.sysread(4096)
384
+ assert_equal expected, received2.sysread(4096)
336
385
  ensure
337
386
  TempServer.destroy_all!
338
387
  end
@@ -357,12 +406,12 @@ class TestMogileFS__MogileFS < TestMogileFS
357
406
  end
358
407
 
359
408
  def test_store_content_http_empty
360
- received = ''
409
+ received = Tempfile.new('received')
361
410
  expected = "PUT /path HTTP/1.0\r\nContent-Length: 0\r\n\r\n"
362
411
  t = TempServer.new(Proc.new do |serv, accept|
363
412
  client, client_addr = serv.accept
364
413
  client.sync = true
365
- received = client.recv(4096, 0)
414
+ received.syswrite(client.recv(4096, 0))
366
415
  client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
367
416
  client.close
368
417
  end)
@@ -373,7 +422,8 @@ class TestMogileFS__MogileFS < TestMogileFS
373
422
  }
374
423
 
375
424
  @client.store_content 'new_key', 'test', ''
376
- assert_equal expected, received
425
+ received.sysseek(0)
426
+ assert_equal expected, received.sysread(4096)
377
427
  end
378
428
 
379
429
  def test_store_content_nfs
@@ -406,17 +456,19 @@ class TestMogileFS__MogileFS < TestMogileFS
406
456
  assert_equal expect_size + header.size, expect.stat.size
407
457
  assert_equal expect_size, to_put.stat.size
408
458
 
409
- readed = 0
459
+ readed = Tempfile.new('readed')
410
460
  t = TempServer.new(Proc.new do |serv, accept|
411
461
  client, client_addr = serv.accept
412
462
  client.sync = true
463
+ nr = 0
413
464
  loop do
414
465
  buf = client.readpartial(8192) or break
415
466
  break if buf.length == 0
416
467
  assert_equal buf.length, received.syswrite(buf)
417
- readed += buf.length
418
- break if readed >= expect.stat.size
468
+ nr += buf.length
469
+ break if nr >= expect.stat.size
419
470
  end
471
+ readed.syswrite("#{nr}")
420
472
  client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
421
473
  client.close
422
474
  end)
@@ -427,7 +479,8 @@ class TestMogileFS__MogileFS < TestMogileFS
427
479
  }
428
480
 
429
481
  @client.store_file('new_key', 'test', to_put.path)
430
- assert_equal expect.stat.size, readed
482
+ readed.sysseek(0)
483
+ assert_equal expect.stat.size, readed.sysread(4096).to_i
431
484
 
432
485
  ENV['PATH'].split(/:/).each do |path|
433
486
  cmp_bin = "#{path}/cmp"
data/test/test_network.rb CHANGED
@@ -24,4 +24,32 @@ class TestNetwork < Test::Unit::TestCase
24
24
  TempServer.destroy_all!
25
25
  end
26
26
 
27
+ def test_verify_non_existent
28
+ good = TempServer.new(Proc.new do |serv,port|
29
+ client,client_addr = serv.accept
30
+ client.readpartial(4096)
31
+ client.syswrite("HTTP/1.0 200 OK\r\nContent-Length: 0\r\n\r\n")
32
+ end)
33
+ bad = TempServer.new(Proc.new { |serv,port| serv.close })
34
+
35
+ good_uri = URI.parse("http://127.0.0.1:#{good.port}/")
36
+ bad_uri = URI.parse("http://127.0.0.1:#{bad.port}/")
37
+ ok = verify_uris([ good_uri, bad_uri ])
38
+ assert_equal [ good_uri ], ok
39
+ ensure
40
+ TempServer.destroy_all!
41
+ end
42
+
43
+ def test_verify_all_bad
44
+ good = TempServer.new(Proc.new { |serv,port| serv.close })
45
+ bad = TempServer.new(Proc.new { |serv,port| serv.close })
46
+
47
+ good_uri = URI.parse("http://127.0.0.1:#{good.port}/")
48
+ bad_uri = URI.parse("http://127.0.0.1:#{bad.port}/")
49
+ ok = verify_uris([ good_uri, bad_uri ], '200', 1.0)
50
+ assert ok.empty?, "nothing returned"
51
+ ensure
52
+ TempServer.destroy_all!
53
+ end
54
+
27
55
  end
data/test/test_util.rb CHANGED
@@ -1,24 +1,23 @@
1
1
  require 'test/setup'
2
- require 'tempfile'
3
2
 
4
3
  class TestMogileFS__Util < Test::Unit::TestCase
5
4
  include MogileFS::Util
6
5
 
7
6
  def test_mogilefs_write
8
- done = Queue.new
7
+ rd, wr = IO.pipe
9
8
 
10
9
  svr = Proc.new do |serv, port|
11
10
  client, client_addr = serv.accept
12
11
  client.sync = true
13
- readed = 0
12
+ nr = 0
14
13
  loop do
15
14
  begin
16
- readed += client.readpartial(16384).length
15
+ nr += client.readpartial(16384).length
17
16
  rescue EOFError
18
17
  break
19
18
  end
20
19
  end
21
- done << readed
20
+ wr.syswrite("#{nr}\n")
22
21
  client.close rescue nil
23
22
  end
24
23
  t = TempServer.new(svr)
@@ -32,14 +31,13 @@ class TestMogileFS__Util < Test::Unit::TestCase
32
31
 
33
32
  syswrite_full(s, big_string)
34
33
  s.close rescue nil
35
- readed = done.pop
36
-
37
- assert_equal((sent + big_string.length), readed)
34
+ IO.select([rd])
35
+ assert_equal((sent + big_string.length), rd.sysread(4096).to_i)
36
+ ensure
37
+ t.destroy!
38
38
  end
39
39
 
40
40
  def test_write_timeout
41
- done = Queue.new
42
-
43
41
  svr = Proc.new do |serv, port|
44
42
  client, client_addr = serv.accept
45
43
  client.sync = true
@@ -54,6 +52,8 @@ class TestMogileFS__Util < Test::Unit::TestCase
54
52
 
55
53
  assert_raises(MogileFS::Timeout) { syswrite_full(s, big_string, 0.1) }
56
54
  s.close rescue nil
55
+ ensure
56
+ t.destroy!
57
57
  end
58
58
 
59
59
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mogilefs-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Wong
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-02-02 00:00:00 -08:00
13
+ date: 2009-02-25 00:00:00 -08:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -31,7 +31,7 @@ dependencies:
31
31
  requirements:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: 1.8.2
34
+ version: 1.8.3
35
35
  version:
36
36
  description: git://git.bogomips.org/mogilefs-client.git
37
37
  email: normalperson@yhbt.net